GCC Code Coverage Report


source/XpertMassCore/src/
File: source/XpertMassCore/src/CleavageMotif.cpp
Date: 2025-11-19 15:26:11
Lines:
166/205
81.0%
Functions:
19/21
90.5%
Branches:
115/270
42.6%

Line Branch Exec Source
1 /* BEGIN software license
2 *
3 * MsXpertSuite - mass spectrometry software suite
4 * -----------------------------------------------
5 * Copyright(C) 2009,...,2018 Filippo Rusconi
6 *
7 * http://www.msxpertsuite.org
8 *
9 * This file is part of the MsXpertSuite project.
10 *
11 * The MsXpertSuite project is the successor of the massXpert project. This
12 * project now includes various independent modules:
13 *
14 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
15 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
16 *
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 *
30 * END software license
31 */
32
33
34 /////////////////////// Local includes
35 #include "MsXpS/libXpertMassCore/CleavageMotif.hpp"
36 #include "MsXpS/libXpertMassCore/Polymer.hpp"
37 #include "MsXpS/libXpertMassCore/PolChemDef.hpp"
38
39 namespace MsXpS
40 {
41
42 namespace libXpertMassCore
43 {
44
45
46 /*!
47 \class MsXpS::libXpertMassCore::CleavageMotif
48 \inmodule libXpertMassCore
49 \ingroup PolChemDefAqueousChemicalReactions
50 \inheaderfile CleavageMotif.hpp
51
52 \brief The CleavageMotif class provides a model for specifying aqueous cleavage
53 motfis of \l{Polymer} \l{Sequence}s.
54
55 When a polymer sequence cleavage occurs, using, for example, the Trypsin
56 cleavage agent, that cleavage agent specifies that cleavage should occur at the
57 following sites "Lys/;Arg/;-Lys/Pro".
58
59 The "Lys/;Arg/;-Lys/Pro" string of sites gets parsed and \e{cleavage motifs} are
60 generated from it. In this specific case, we'll have three \e{CleavageMotif}
61 instances with the following data:
62
63 - First motif (or cleavage site):
64 - "Lys"
65 - monomer container: [0] = "Lys"
66 - offset = 1 ('/' indicates that the cut is right of monomer)
67 - is for cleavage ? = Enums::CleavageAction::CLEAVE
68
69 - Second motif (or cleavage site):
70 - "Arg"
71 - monomer container: [0] = "Arg"
72 - offset = 1 ('/' indicates that the cut is right of monomer)
73 - is for cleavage ? = Enums::CleavageAction::CLEAVE
74
75 - Third motif (or non-cleavage site):
76 - "-LysPro"
77 - monomer container: [0] = "Lys", [1] = "Pro"
78 - offset = 1 ('/' indicates that the cut is right of monomer)
79 - is for cleavage ? = Enums::CleavageAction::NO_CLEAVE
80
81 Thanks to this deconstruction (from "Lys/;Arg/;-Lys/Pro" to the 3 cleavage
82 motifs above) is the polymer sequence cleaved according to the
83 cleavage agent specification.
84
85 \sa CleavageAgent, CleavageRule
86 */
87
88
89 /*!
90 \variable MsXpS::libXpertMassCore::CleavageMotif::mcsp_polChemDef
91
92 \brief The \l PolChemDef (polymer chemistry definition) that is needed.
93 */
94
95 /*!
96 \variable MsXpS::libXpertMassCore::CleavageMotif::m_monomers
97
98 \brief The container of Monomer instances. The Monomer instances
99 are in the form of const shared pointers to Monomer in the
100 polymer chemistry definition.
101
102 A "Lys/Pro" motif will translate into two Monomer instances (actually pointers)
103 having codes Lys and Pro, in the right order.
104 */
105
106 /*!
107 \variable MsXpS::libXpertMassCore::CleavageMotif::m_offset
108
109 \brief The offset between the actual cleavage site and the first monomer of the
110 motif.
111
112 In the The "Lys/", "Arg/" and "-Lys/Pro" examples, the offset would be 1 for
113 each motif, because each time the cleavage occurs after the first monomer
114 code: Lys/, or Arg/ or Lys/Pro. In the /Asp cleavage site the offset would be 0,
115 because the cleavage occurs before the first monomer in the motif (Asp). In the
116 ATGC/GCAT cleavage motif, the offset would be 4.
117 */
118
119 /*!
120 \variable MsXpS::libXpertMassCore::CleavageMotif::m_cleavageAction
121
122 \brief Tells if the motif is for cleavage or not for cleavage.
123
124 In the "Lys/" and "Arg/" motif, that would be true; for "-Lys/Pro", that would
125 be false, because Trypsin does not cleave after a Lysyl residue if it is
126 followed by a Prolyl residue.
127 */
128
129 /*!
130 \variable MsXpS::libXpertMassCore::CleavageMotif::m_isValid
131 \brief Tell the validity status of the CleavageMotif instance.
132 */
133
134 /*!
135 \brief Constructs a cleavage motif with \a pol_chem_def_csp as the polymer chemistry definition.
136
137 The instance will be invalid (m_isValid set to false).
138 */
139 3420 CleavageMotif::CleavageMotif(PolChemDefCstSPtr pol_chem_def_csp)
140 3420 : mcsp_polChemDef(pol_chem_def_csp)
141 {
142 3420 }
143
144 /*!
145 \brief Constructs a cleavage motif with a number of parameters.
146
147 \list
148 \li \a pol_chem_def_csp Polymer chemistry definition. Cannot be nullptr.
149
150 \li \a motif Motif in the form of "Lys/" or "Lys/Pro" or "/Asp".
151
152 \li \a offset Offset position of the cleavage to the first monomer code in
153 the motif.
154
155 \li \a cleavage_action Tells if motif is for cleavage (for example, "Lys/") or
156 not for cleavage (for example, "-Lys/Pro").
157 \endlist
158
159 After setting the member data, the CleavageMotif instance is validated and
160 m_isValid is set to the result of this validation.
161 */
162 12 CleavageMotif::CleavageMotif(PolChemDefCstSPtr pol_chem_def_csp,
163 const QString &motif,
164 int offset,
165 12 Enums::CleavageAction cleavage_action)
166 12 : mcsp_polChemDef(pol_chem_def_csp),
167 12 m_offset(offset),
168
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 m_cleavageAction(cleavage_action)
169 {
170
2/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 if(!parseMotif(motif))
171 qCritical()
172 << "Upon construction of CleavageMotif, the motif could not be parsed.";
173
174 // Let's see the other members.
175 12 ErrorList error_list;
176
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 m_isValid = validate(&error_list);
177
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(!m_isValid)
179 qCritical() << "Upon construction of CleavageMotif, the instance failed to "
180 "validate with errors:"
181 << Utils::joinErrorList(error_list, ", ");
182
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
12 }
183
184 /*!
185 \brief Constructs a CleavageMotif instance as a copy of \a other.
186
187 After setting the member data, the CleavageMotif instance is validated and
188 m_isValid is set to the result of this validation.
189 */
190 3 CleavageMotif::CleavageMotif(const CleavageMotif &other)
191 3 : mcsp_polChemDef(other.mcsp_polChemDef),
192 3 m_offset(other.m_offset),
193
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 m_cleavageAction(other.m_cleavageAction)
194 {
195
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 m_monomers = other.m_monomers;
196
197 // Let's see the other members.
198 3 ErrorList error_list;
199
200
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 m_isValid = validate(&error_list);
201
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(!m_isValid)
203 qCritical() << "Upon copy-construction of CleavageMotif, the instance "
204 "failed to validate with errors:"
205 << Utils::joinErrorList(error_list, ", ");
206
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
3 }
207
208 /*!
209 \brief Destructs this CleavageMotif instance.
210 */
211 375 CleavageMotif::~CleavageMotif()
212 {
213 375 m_monomers.clear();
214
2/2
✓ Branch 1 taken 372 times.
✓ Branch 2 taken 3 times.
375 }
215
216 /*!
217 \brief Sets the PolChemDef member to \a pol_chem_def_csp.
218
219 This instance then undergoes validation and m_isValid is set to the result of
220 it.
221 */
222 void
223 12 CleavageMotif::setPolChemDefCstSPtr(PolChemDefCstSPtr pol_chem_def_csp)
224 {
225 12 mcsp_polChemDef = pol_chem_def_csp;
226
227 12 ErrorList error_list;
228
229
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 m_isValid = validate(&error_list);
230
231
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if(!m_isValid)
232
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
24 qCritical() << "Upon setting PolChemDef of CleavageMotif, the instance "
233
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 "failed to validate with errors:"
234
3/6
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
24 << Utils::joinErrorList(error_list, ", ");
235 12 }
236
237 /*!
238 \brief Returns the \l PolChemDef.
239 */
240 PolChemDefCstSPtr
241 CleavageMotif::getPolChemDefCstSPtr() const
242 {
243 return mcsp_polChemDef;
244 }
245
246 /*!
247 \brief Parses the \a motif and fills-in the member container of Monomers as a
248 result of the parsing.
249
250 \sa parseMotif()
251 */
252 void
253 12 CleavageMotif::setMotif(const QString &motif)
254 {
255
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 if(!parseMotif(motif))
256 {
257 qCritical()
258 << "Upon setting motif string of CleavageMotif, the motif could "
259 "not be parsed.";
260 m_isValid = false;
261 }
262
263 // Let's see the other members.
264 12 ErrorList error_list;
265
266
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 m_isValid = validate(&error_list);
267
268
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 if(!m_isValid)
269
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
18 qCritical() << "Upon setting motif of CleavageMotif, the instance "
270
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 "failed to validate with errors:"
271
3/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
18 << Utils::joinErrorList(error_list, ", ");
272 12 }
273
274 /*!
275 \brief Returns the motif as a concatenation of the codes of the Monomer
276 instances found in the member container of Monomers.
277 */
278 QString
279 39 CleavageMotif::getMotif() const
280 {
281 39 QString text;
282
283
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 39 times.
93 for(const MonomerSPtr &monomer_csp : m_monomers)
284
1/2
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
108 text += monomer_csp->getCode();
285
286 39 return text;
287 }
288
289 /*!
290 \brief Returns a const reference to the container of Monomers.
291 */
292 const std::vector<MonomerSPtr> &
293 894 CleavageMotif::getMonomersCstRef() const
294 {
295 894 return m_monomers;
296 }
297
298 /*!
299 \brief Returns a reference to the container of Monomers.
300 */
301 std::vector<MonomerSPtr> &
302 CleavageMotif::getMonomersRef()
303 {
304 return m_monomers;
305 }
306
307 /*!
308 \brief Sets the \a offset.
309
310 The offset is the position of the cleavage inside the motif, with reset to the
311 first monomer code in that motif. For example, for a cleavage site "Lys/Pro",
312 the cleavage motif becomes {"Lys", "Pro"} and the offset is 1, while for a site
313 "/Asp", the cleavage motif becomes {"Asp"} and the offset is 0.
314
315 An offset value can thus not be greater than the number of Monomer codes in the
316 motif.
317
318 This instance then undergoes validation and m_isValid is set to the result of
319 it.
320 */
321 void
322 6 CleavageMotif::setOffset(int offset)
323 {
324 6 m_offset = offset;
325
326 6 ErrorList error_list;
327
328
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 m_isValid = validate(&error_list);
329
330
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if(!m_isValid)
331
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
12 qCritical() << "Upon setting offset of CleavageMotif, the instance "
332
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 "failed to validate with errors:"
333
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
12 << Utils::joinErrorList(error_list, ", ");
334 6 }
335
336 /*!
337 \brief Returns the offset.
338 */
339 int
340 735 CleavageMotif::getOffset() const
341 {
342 735 return m_offset;
343 }
344
345 /*!
346 \brief Sets the member Enums::CleavageAction to \a cleavage_action.
347
348 This instance then undergoes validation and m_isValid is set to the result of
349 it.
350 */
351 void
352 3393 CleavageMotif::setCleavageAction(Enums::CleavageAction cleavage_action)
353 {
354 3393 m_cleavageAction = cleavage_action;
355
356 3393 ErrorList error_list;
357
358
1/2
✓ Branch 1 taken 3393 times.
✗ Branch 2 not taken.
3393 m_isValid = validate(&error_list);
359
360
2/2
✓ Branch 0 taken 3378 times.
✓ Branch 1 taken 15 times.
3393 if(!m_isValid)
361
1/2
✓ Branch 1 taken 3378 times.
✗ Branch 2 not taken.
6756 qCritical()
362 << "Upon setting cleave operation of CleavageMotif, the instance "
363
1/2
✓ Branch 1 taken 3378 times.
✗ Branch 2 not taken.
3378 "failed to validate with errors:"
364
3/6
✓ Branch 1 taken 3378 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3378 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3378 times.
✗ Branch 8 not taken.
6756 << Utils::joinErrorList(error_list, ", ");
365 3393 }
366
367 /*!
368 \brief Returns if motif is for cleavage or not.
369 */
370 Enums::CleavageAction
371 735 CleavageMotif::getCleavageAction() const
372 {
373 735 return m_cleavageAction;
374 }
375
376 /*!
377 \brief Assigns \a other to this CleavageMotif instance.
378
379 This instance then undergoes validation and m_isValid is set to the result of
380 it.
381
382 Returns a reference to this CleavageMotif instance.
383 */
384 CleavageMotif &
385 3 CleavageMotif::operator=(const CleavageMotif &other)
386 {
387
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(&other == this)
388 return *this;
389
390 3 mcsp_polChemDef = other.mcsp_polChemDef;
391 3 m_offset = other.m_offset;
392 3 m_cleavageAction = other.m_cleavageAction;
393
394 3 m_monomers = other.m_monomers;
395
396 3 ErrorList error_list;
397
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 m_isValid = validate(&error_list);
398
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(!m_isValid)
400 qCritical() << "Upon assignment of CleavageMotif, the instance "
401 "failed to validate with errors:"
402 << Utils::joinErrorList(error_list, ", ");
403
404 3 return *this;
405 3 }
406
407 /*!
408 \brief Returns true if \c this and \a other are identical.
409
410 The comparison of the Monomer instances in the member container is deep (that is
411 the Monomer instances are compared and not the shared pointers).
412 */
413 bool
414 75 CleavageMotif::operator==(const CleavageMotif &other) const
415 {
416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if(&other == this)
417 return true;
418
419 // Remember that the motif is actually a vector of MonomerSPtr, so when one
420 // does a copy either via the operator ==() or the copy constructor, the
421 // Motifs are going to be the same.
422
423 // If, then one of the MonomerSPtr is changed, the other is changed also.
424
425 // qDebug() << "Now == comparing cleavage motifs:" << this->getMotif()
426 // << "versus" << other.getMotif();
427
428 // We cannot compare the PolChemDef, because that would cause
429 // an infinite loop: (each instance of this class in the PolChemDef would
430 // try to compare the PolChemDef...).
431
432
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 if(m_offset != other.m_offset ||
433
2/4
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
✗ Branch 3 not taken.
75 m_monomers.size() != other.m_monomers.size() ||
434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 m_cleavageAction != other.m_cleavageAction)
435 {
436 // qDebug() << "Either or both offset or/and cleavage operation differ.";
437 return false;
438 }
439
440
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 147 times.
222 for(std::size_t iter = 0; iter < m_monomers.size(); ++iter)
441 {
442
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 147 times.
147 if(*m_monomers.at(iter).get() != *other.m_monomers.at(iter).get())
443 {
444 // qDebug() << "At least one Monomer instance differ in both
445 // CleavageMotif instances.";
446 return false;
447 }
448 }
449
450 return true;
451 }
452
453 /*!
454 \brief Returns true if \c this and \a other are different.
455
456 Returns the negated result of operator==().
457 */
458 bool
459 195 CleavageMotif::operator!=(const CleavageMotif &other) const
460 {
461
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 126 times.
195 if(&other == this)
462 return false;
463
464 69 return !operator==(other);
465 }
466
467 /*!
468 \brief Parses the cleavage \a site and returns the count of Monomer
469 instances stored in the member container as a result of parsing the \a site.
470
471 A cleavage site is a string in the form "Lys/Pro" or "/Asp". The member
472 container of Monomer pointers is filled-in with pointers to the PolChemDef's
473 Monomer instances having codes {Lys, Pro} or {Asp}. The offset is the position
474 of the
475 '/' cleavage symbol (that is, the actual cleavage position in the motif). For
476 "Lys/Pro", the offset is 1 while for "/Asp", the offset is 0.
477
478 After setting the member data, the CleavageMotif instance is validated and
479 m_isValid is set to the result of this validation.
480 */
481 std::size_t
482 3402 CleavageMotif::parseSite(const QString &site)
483 {
484 3402 m_monomers.clear();
485
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3402 times.
3402 if(mcsp_polChemDef == nullptr || mcsp_polChemDef.get() == nullptr)
487 {
488 qCritical()
489 << "Cannot parse cleavage site without any available PolChemDef.";
490 m_isValid = false;
491 return 0;
492 }
493
494
2/4
✓ Branch 1 taken 3402 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3402 times.
✗ Branch 5 not taken.
3402 if(site.count('/') == 0 || site.count('/') > 1)
495 {
496 qCritical() << "Cannot parse cleavage site: either missing '/' cleavage "
497 "indicator or more than one.";
498 m_isValid = false;
499 return 0;
500 }
501
502 3402 std::size_t code_length = mcsp_polChemDef->getCodeLength();
503
504 3402 std::size_t monomer_count = 0;
505
506 3402 QRegularExpression single_monomer_code_regexp(
507
2/4
✓ Branch 2 taken 3402 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3402 times.
✗ Branch 6 not taken.
6804 QString("([/]?)([A-Z][a-z]{0,%1})([/]?)").arg(code_length - 1));
508
509
1/2
✓ Branch 1 taken 3402 times.
✗ Branch 2 not taken.
3402 for(const QRegularExpressionMatch &match :
510
4/6
✓ Branch 1 taken 3402 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3402 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3978 times.
✓ Branch 7 taken 3402 times.
7380 single_monomer_code_regexp.globalMatch(site))
511 {
512
1/2
✓ Branch 1 taken 3978 times.
✗ Branch 2 not taken.
3978 QString sub_match = match.captured(0);
513 // qDebug() << "Entering single_monomer_code_regexp sub-match:" <<
514 // sub_match;
515
516
1/2
✓ Branch 1 taken 3978 times.
✗ Branch 2 not taken.
3978 QString ant_cleave = match.captured(1);
517 // qDebug() << "ant_cleave:" << ant_cleave;
518
519
1/2
✓ Branch 1 taken 3978 times.
✗ Branch 2 not taken.
3978 QString code = match.captured(2);
520 // qDebug() << "Parsed code:" << code;
521
522
1/2
✓ Branch 1 taken 3978 times.
✗ Branch 2 not taken.
3978 QString post_cleave = match.captured(3);
523 // qDebug() << "post_cleave:" << post_cleave;
524
525
2/2
✓ Branch 0 taken 822 times.
✓ Branch 1 taken 3156 times.
3978 if(!ant_cleave.isEmpty())
526 822 m_offset = monomer_count;
527
528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3978 times.
3978 if(code.isEmpty())
529 qFatalStream() << "Programming error: code cannot be empty.";
530
531 3978 const MonomerSPtr monomer_csp =
532
1/2
✓ Branch 1 taken 3978 times.
✗ Branch 2 not taken.
3978 mcsp_polChemDef->getMonomerCstSPtrByCode(code);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3978 times.
3978 if(monomer_csp == nullptr)
534 qFatalStream()
535 << "Programming error. The monomer code must be known to the "
536 "PolChemDef.";
537
538
1/2
✓ Branch 1 taken 3978 times.
✗ Branch 2 not taken.
3978 m_monomers.push_back(monomer_csp);
539 3978 ++monomer_count;
540
541
2/2
✓ Branch 0 taken 2580 times.
✓ Branch 1 taken 1398 times.
3978 if(!post_cleave.isEmpty())
542 2580 m_offset = monomer_count;
543
1/2
✓ Branch 5 taken 3978 times.
✗ Branch 6 not taken.
7380 }
544
545 3402 ErrorList error_list;
546
547
1/2
✓ Branch 1 taken 3402 times.
✗ Branch 2 not taken.
3402 m_isValid = validate(&error_list);
548
549
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 3378 times.
3402 if(!m_isValid)
550
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
48 qCritical() << "Upon parsing cleavage site in CleavageMotif, the instance "
551
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 "failed to validate with errors:"
552
3/6
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 24 times.
✗ Branch 8 not taken.
48 << Utils::joinErrorList(error_list, ", ");
553
554 3402 return m_monomers.size();
555 3402 }
556
557 /*!
558 \brief Parses the cleavage \a motif and returns the count of Monomer
559 instances stored in m_monomers as a result of parsing the \a motif.
560
561 A cleavage motif is a string in the form "LysPro" or "Asp" (in fact that is
562 the string representation of a \l{Sequence}).
563 */
564 std::size_t
565 24 CleavageMotif::parseMotif(const QString &motif)
566 {
567 24 m_monomers.clear();
568
569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if(mcsp_polChemDef == nullptr || mcsp_polChemDef.get() == nullptr)
570 {
571 qCritical() << "Cannot parse motif without any available PolChemDef;";
572 m_isValid = false;
573 return 0;
574 }
575
576
1/2
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 Sequence motif_sequence(mcsp_polChemDef, motif);
577
578 24 ErrorList error_list;
579
2/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
24 if(!motif_sequence.validate(&error_list))
580 {
581 qCritical()
582 << "The motif" << motif
583 << "failed to convert to a valid Sequence object, with errors:"
584 << Utils::joinErrorList(error_list, ", ");
585 m_isValid = false;
586 return 0;
587 }
588
589
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 motif_sequence.cleanupMonomers();
590
3/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 24 times.
105 for(const MonomerSPtr &monomer_sp : motif_sequence.getMonomersCstRef())
591 {
592
1/2
✓ Branch 1 taken 81 times.
✗ Branch 2 not taken.
81 m_monomers.push_back(monomer_sp);
593 // qDebug() << "Pushed back monomer:" << monomer_csp->toString();
594 }
595
596 24 return m_monomers.size();
597 24 }
598
599 /*!
600 \brief Returns true if validation of this CleavageMotif instance was successful,
601 false otherwise.
602
603 If errors are encountered and \a error_list_p is not nullptr, then these error are stored in that ErrorList.
604 */
605 bool
606 10746 CleavageMotif::validate(ErrorList *error_list_p) const
607 {
608 10746 m_isValid = true;
609
610
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10743 times.
10746 if(mcsp_polChemDef == nullptr || mcsp_polChemDef.get() == nullptr)
611 {
612 6 qCritical() << "A CleavageMotif with no PolChemDef available cannot "
613
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 "validate successfully.";
614
615 3 m_isValid = false;
616
617
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(error_list_p != nullptr)
618 6 error_list_p->push_back(
619 "A CleavageMotif with no PolChemDef available cannot validate "
620 "successfully");
621 }
622
623
2/2
✓ Branch 0 taken 3396 times.
✓ Branch 1 taken 7350 times.
10746 if(m_monomers.size() == 0)
624 {
625 6792 qCritical() << "A CleavageMotif with no Monomer motif cannot validate "
626
1/2
✓ Branch 1 taken 3396 times.
✗ Branch 2 not taken.
3396 "successfully.";
627
628 3396 m_isValid = false;
629
630
1/2
✓ Branch 0 taken 3396 times.
✗ Branch 1 not taken.
3396 if(error_list_p != nullptr)
631 6792 error_list_p->push_back(
632 "A CleavageMotif with no Monomer motif cannot validate successfully");
633 }
634
635
2/2
✓ Branch 0 taken 3405 times.
✓ Branch 1 taken 7341 times.
10746 if(m_offset > m_monomers.size())
636 {
637 6810 qCritical()
638 << "A CleavageMotif with an offset greater than the number of "
639
1/2
✓ Branch 1 taken 3405 times.
✗ Branch 2 not taken.
3405 "Monomer codes in the motif cannot validate successfully.";
640
641 3405 m_isValid = false;
642
643
1/2
✓ Branch 0 taken 3405 times.
✗ Branch 1 not taken.
3405 if(error_list_p != nullptr)
644 6810 error_list_p->push_back(
645 "A CleavageMotif with an offset greater than the number of "
646 "Monomer codes in the motif cannot validate successfully");
647 }
648
649
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 10671 times.
10746 if(m_cleavageAction == Enums::CleavageAction::NOT_SET)
650 {
651 150 qCritical() << "A CleavageMotif with no set Enums::CleavageAction cannot "
652
1/2
✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
75 "validate successfully.";
653
654 75 m_isValid = false;
655
656
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 if(error_list_p != nullptr)
657 150 error_list_p->push_back(
658 "A CleavageMotif with no set Enums::CleavageAction cannot validate "
659 "successfully");
660 }
661
662 10746 return m_isValid;
663 }
664
665 /*
666 \brief Returns the validity status of this CleavageMotif instance.
667 */
668 bool
669 3462 CleavageMotif::isValid() const
670 {
671 3462 return m_isValid;
672 }
673
674
675 } // namespace libXpertMassCore
676 } // namespace MsXpS
677