GCC Code Coverage Report


./
File: src/XpertMass/CleaveMotif.cpp
Date: 2024-08-24 11:26:06
Lines:
34/91
37.4%
Functions:
3/15
20.0%
Branches:
15/64
23.4%

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 "CleaveMotif.hpp"
36 #include "Polymer.hpp"
37 #include "PolChemDef.hpp"
38
39
40 namespace MsXpS
41 {
42
43 namespace libXpertMass
44 {
45
46
47 /*!
48 \class MsXpS::libXpertMass::CleaveMotif
49 \inmodule libXpertMass
50 \ingroup PolChemDefAqueousChemicalReactions
51 \inheaderfile CleaveMotif.hpp
52
53 \brief The CleaveMotif class provides a model for specifying aqueous cleavage
54 sites of \l{Polymer} \l{Sequence}s.
55
56 When a polymer sequence cleavage occurs, using, for example, the
57 specification "Lys/;Arg/;-Lys/Pro", a number of actions need be
58 performed prior to listing the oligomers obtained as a result of the
59 cleavage.
60
61 The "Lys/;Arg/;-Lys/Pro" cleavage specification (\l CleaveSpec) gets crunched
62 in a number of steps and cleavage motifs are generated for it. In this specific
63 case we'll have three motifs with the following data:
64
65 - First motif (or cleavage site):
66 - "Lys/"
67 - code list [0] = "Lys"
68 - offset = 1 ('/' indicates that cut is right of monomer)
69 - is for cleavage ? = true
70
71 - Second motif (or cleavage site):
72 - "Arg/"
73 - code list [0] = "Arg"
74 - offset = 1 ('/' indicates that cut is right of monomer)
75 - is for cleavage ? = true
76
77 - Third motif (or non-cleavage site):
78 - "-Lys/Pro"
79 - code list [0] = "Lys", [1] = "Pro"
80 - offset = 1 ('/' indicates that cut is right of monomer)
81 - is for cleavage ? = false
82
83 Thanks to this deconstruction (from "Lys/;Arg/;-Lys/Pro" to the 3
84 motifs above) is the polymer sequence cleaved according to the
85 specification.
86
87 \sa CleaveSpec, CleaveRule
88 */
89
90
91 /*!
92 \variable MsXpS::libXpertMass::CleaveMotif::m_motif
93
94 \brief The string motif that describes a specific cleavage site.
95
96 The "Lys/" cleavage motif is part of the cleavage specification that describes
97 the model for the Trypsin cleavage in the proteinaceous world.
98 */
99
100 /*!
101 \variable MsXpS::libXpertMass::CleaveMotif::m_codeList
102
103 \brief The list of \l Monomer codes that are in the string motif.
104
105 For the "-Lys/Pro" motif, also from the Trypsin cleavage specification, there
106 are two codes: "Lys" and "Pro".
107 */
108
109 /*!
110 \variable MsXpS::libXpertMass::CleaveMotif::m_offset
111
112 \brief The cleavage site offset with respect to the first monomer code of the
113 motif.
114
115 In the The "Lys/", "Arg/" and "-Lys/Pro" examples, the offset would be 1 for
116 each motif, because each time the cleavage occurs after the first monomer
117 code: Lys/, or Arg/ or Lys/Pro.
118 */
119
120 /*!
121 \variable MsXpS::libXpertMass::CleaveMotif::m_isForCleave
122
123 \brief Tells if the motif is for cleavage.
124
125 In the "Lys/" and "Arg/" motif, that would be true; for "-Lys/Pro", that would
126 be false, because Trypsin does not cleave after a Lysil residue if it is
127 followed by a Prolyl residue.
128 */
129
130
131 /*!
132 \brief Constructs a cleavage motif.
133
134 \a pol_chem_def_csp Polymer chemistry definition. Cannot be nullptr.
135
136 \a name Name. Cannot be empty.
137
138 \a motif Motif in the form of "Lys/" or "-Lys/Pro".
139
140 \a offset Offset position of the cleavage to the first monomer code in
141 the motif.
142
143 \a is_for_cleavage Tells if motif is for cleavage (for example, "Lys/") or
144 not for cleavage (for example, "-Lys/Pro").
145 */
146 5880 CleaveMotif::CleaveMotif(PolChemDefCstSPtr pol_chem_def_csp,
147 QString name,
148 const QString &motif,
149 int offset,
150 5880 bool is_for_cleavage)
151 : PolChemDefEntity(pol_chem_def_csp, name),
152 5880 m_motif(motif),
153 5880 m_offset(offset),
154
1/2
✓ Branch 2 taken 5880 times.
✗ Branch 3 not taken.
5880 m_isForCleave(is_for_cleavage)
155 {
156 5880 }
157
158 /*!
159 \brief Constructs a CleaveMotif instance as a copy of \a other.
160 */
161 CleaveMotif::CleaveMotif(const CleaveMotif &other)
162 : PolChemDefEntity(other),
163 m_motif(other.m_motif),
164 m_codeList(other.m_codeList),
165 m_offset(other.m_offset),
166 m_isForCleave(other.m_isForCleave)
167 {
168 }
169
170 /*!
171 \brief Destructs this CleaveMotif instance.
172 */
173 CleaveMotif::~CleaveMotif()
174 {
175 }
176
177 /*!
178 \brief Assigns \a other to this CleaveMotif instance.
179
180 Returns a reference to this CleaveMotif instance.
181 */
182 CleaveMotif &
183 CleaveMotif::operator=(const CleaveMotif &other)
184 {
185 if(&other == this)
186 return *this;
187
188 PolChemDefEntity::operator=(other);
189
190 m_motif = other.m_motif;
191 m_codeList = other.m_codeList;
192 m_offset = other.m_offset;
193 m_isForCleave = other.m_isForCleave;
194
195 return *this;
196 }
197
198 /*!
199 \brief Returns true if \c this and \a other are identical.
200 */
201 bool
202 CleaveMotif::operator==(const CleaveMotif &other) const
203 {
204 if(&other == this)
205 return true;
206
207 if(PolChemDefEntity::operator!=(other))
208 return false;
209 if(m_motif != other.m_motif)
210 return false;
211 if(m_codeList != other.m_codeList)
212 return false;
213 if(m_offset != other.m_offset)
214 return false;
215 if(m_isForCleave != other.m_isForCleave)
216 return false;
217
218 return true;
219 }
220
221 /*!
222 \brief Returns true if \c this and \a other are different.
223
224 Returns the negated result of operator==().
225 */
226 bool
227 CleaveMotif::operator!=(const CleaveMotif &other) const
228 {
229 if(&other == this)
230 return false;
231
232 return !operator==(other);
233 }
234
235 /*!
236 \brief Sets the \a motif.
237 */
238 void
239 CleaveMotif::setMotif(const QString &motif)
240 {
241 m_motif = motif;
242 }
243
244 /*!
245 \brief Returns the motif.
246 */
247 const QString &
248 CleaveMotif::motif()
249 {
250 return m_motif;
251 }
252
253 /*!
254 \brief Returns the string list of codes in the motif.
255 */
256 const QStringList &
257 CleaveMotif::codeList() const
258 {
259 return m_codeList;
260 }
261
262 /*!
263 \brief Sets the \a offset.
264 */
265 void
266 CleaveMotif::setOffset(int offset)
267 {
268 m_offset = offset;
269 }
270
271 /*!
272 \brief Returns the offset.
273 */
274 int
275 CleaveMotif::offset()
276 {
277 return m_offset;
278 }
279
280 /*!
281 \brief Sets if motif is for cleavage to \a for_cleave.
282 */
283 void
284 5880 CleaveMotif::setForCleave(bool for_cleave)
285 {
286 5880 m_isForCleave = for_cleave;
287 5880 }
288
289 /*!
290 \brief Returns if motif is for cleavage.
291 */
292 bool
293 CleaveMotif::isForCleave()
294 {
295 return m_isForCleave;
296 }
297
298 /*!
299 \brief Parses the cleavage \a site.
300
301 Upon parsing of the cleavage \a site, this CleaveMotif instance is filled with
302 data.
303
304 Returns the number of monomer codes in the motif, or -1 upon error.
305 */
306 int
307 5880 CleaveMotif::parse(const QString &site)
308 {
309
1/2
✓ Branch 2 taken 5880 times.
✗ Branch 3 not taken.
5880 const QList<Monomer *> &refList = mcsp_polChemDef->monomerList();
310
311 5880 QString code;
312 5880 QString error;
313 5880 QString local = site;
314
315 5880 int index = 0;
316 5880 int count = 0;
317
318 // We get something like "Lys/Pro" or something like "KKGK/RRGK" and
319 // we have to make three things:
320 //
321 // 1. change the site "KKGK/RRGK" to a motif string(KKGKRRGK).
322 //
323 // 2. set the offset member to the index of '/' in the initial site
324 // string.
325 //
326 // 3. make an array of codes with the motif.
327
328
1/2
✓ Branch 1 taken 5880 times.
✗ Branch 2 not taken.
5880 Sequence sequence(local);
329
330 while(1)
331 {
332 18424 code.clear();
333
334
2/4
✓ Branch 1 taken 18424 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18424 times.
✗ Branch 5 not taken.
18424 if(sequence.nextCode(
335
2/2
✓ Branch 1 taken 5880 times.
✓ Branch 2 taken 12544 times.
36848 &code, &index, &error, mcsp_polChemDef->codeLength()) == -1)
336 {
337
1/2
✓ Branch 1 taken 5880 times.
✗ Branch 2 not taken.
5880 if(error == "/")
338 {
339 5880 m_offset = count;
340
341 // qDebug() << __FILE__ << __LINE__
342 // << "Found / at code position" << m_offset;
343
344 // Increment index so that we iterate in the next code
345 // at next round.
346 5880 ++index;
347
348 5880 continue;
349 }
350
351 // There was an error parsing the site sequence. If the err
352 // string contains a space, that is not serious, we could
353 // skip that.
354
355 qDebug() << __FILE__ << __LINE__ << "Failed to parse cleavage site"
356 << site;
357
358 return -1;
359 }
360
361 // There might have been no error, but that does not means that
362 // we necessarily got a code.
363
2/2
✓ Branch 1 taken 5880 times.
✓ Branch 2 taken 6664 times.
12544 if(code.isEmpty())
364 {
365 // We arrived at the end of a code parsing step(either
366 // because the current 'local' cleavage site(that is
367 // 'sequence') was finished parsing or because we finished
368 // parsing one of its monomer codes.
369 5880 break;
370 }
371
372 // At this point we actually had a code.
373
374 // qDebug() << __FILE__ << __LINE__
375 // << "Got next code:" << code.toAscii();
376
377 // At this point, 'code' contains something that looks like a
378 // valid code, but we still have to make sure that this code
379 // actually is in our list of monomer codes...
380
381
2/4
✓ Branch 1 taken 6664 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6664 times.
6664 if(Monomer::isCodeInList(code, refList) == -1)
382 {
383 qDebug() << __FILE__ << __LINE__ << "Monomer code" << code
384 << " is not in the monomer list.";
385
386 return -1;
387 }
388
389 // At the end m_motif will contain KKGKRRGK, while site was
390 // "KKGK/RRGK" KKGKRRGK
391
1/2
✓ Branch 1 taken 6664 times.
✗ Branch 2 not taken.
6664 m_motif += code;
392
393 // Add the newly parsed code to the code list.
394
1/2
✓ Branch 1 taken 6664 times.
✗ Branch 2 not taken.
6664 m_codeList << code;
395
396 6664 ++count;
397
398 // Increment index so that we iterate in the next code at next
399 // round.
400 6664 ++index;
401 }
402
403 // Return the number of successfully parsed monomer codes for the
404 // 'site' string.
405
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5880 times.
5880 Q_ASSERT(count == m_codeList.size());
406
407 5880 return count;
408 5880 }
409
410
411 bool
412 CleaveMotif::validate()
413 {
414 Q_ASSERT(0);
415 return true;
416 }
417
418 } // namespace libXpertMass
419
420 } // namespace MsXpS
421