GCC Code Coverage Report


source/XpertMassCore/src/
File: source/XpertMassCore/src/CalcOptions.cpp
Date: 2025-11-19 15:26:11
Lines:
118/131
90.1%
Functions:
27/29
93.1%
Branches:
52/114
45.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 /////////////////////// Qt includes
35 #include <QChar>
36 #include <QDebug>
37 #include <QString>
38
39
40 /////////////////////// Local includes
41 #include "MsXpS/libXpertMassCore/CalcOptions.hpp"
42
43
44 int calcOptionsMetaTypeId =
45 qRegisterMetaType<MsXpS::libXpertMassCore::CalcOptions>(
46 "MsXpS::libXpertMassCore::CalcOptions");
47
48 namespace MsXpS
49 {
50 namespace libXpertMassCore
51 {
52
53
54 /*!
55 \class MsXpS::libXpertMassCore::CalcOptions
56 \inmodule libXpertMassCore
57 \ingroup XpertMassMassCoreCalculations
58 \inheaderfile CalcOptions.hpp
59
60 \brief The CalcOptions class provides the specifications that
61 configure the way masses are calculated for \l{Oligomer}s, \l{Polymer}s and
62 product ions.
63 */
64
65 /*!
66 \variable MsXpS::libXpertMassCore::CalcOptions::m_deepCalculation
67
68 \brief Tells if the calculations must involve the recalculation of all
69 the masses of the \l{Monomer}s in the sequence. This is typically needed when
70 calculating masses involving modified Monomer instances, whereby each Monomer
71 needs to recompute its mass taking into account the Modif instances attached to
72 it.
73 */
74
75 /*!
76 \variable MsXpS::libXpertMassCore::CalcOptions::m_massType
77
78 \brief The mass type to compute, monoisotopic or average.
79
80 \sa Enums::MassType
81 */
82
83 /*!
84 \variable MsXpS::libXpertMassCore::CalcOptions::m_capType
85
86 \brief The cap type, left or right (or both), to account for in the
87 calculations.
88
89 \sa Enums::CapType
90 */
91
92 /*!
93 \variable MsXpS::libXpertMassCore::CalcOptions::m_monomerEntities
94
95 \brief The \l Monomer entities to account for in the calculations.
96
97 \sa Enums::ChemicalEntity
98 */
99
100 /*!
101 \variable MsXpS::libXpertMassCore::CalcOptions::m_polymerEntities
102
103 \brief The \l Polymer entities to account for in the calculations.
104
105 \sa Enums::ChemicalEntity
106 */
107
108 /*!
109 \variable MsXpS::libXpertMassCore::CalcOptions::m_selectionType
110
111 \brief The manner the monomers need to be accounted for: as residual chains
112 or as finished-polymerization state sequences.
113
114 The calculations might consider only the residual chain. In that case, only
115 the mass of the monomers is considered and then the polymer is not in its
116 finished polymerization state. If that latter state is required, then, the
117 residual chain must be capped with both the left and the right end caps.
118
119 \sa MsXpS::libXpertMassCore::Enums::SelectionType
120 */
121
122 /*!
123 \variable MsXpS::libXpertMassCore::CalcOptions::mp_indexRangeCollection
124
125 \brief The IndexRangeCollection container that contains all the IndexRange
126 instances that describes what regions of the \l Polymer need to be accounted for
127 in the calculation. Most generally, there will be only one IndexRange, but there
128 might be situations in which multiple regions might be selected.
129 */
130
131
132 /*!
133 \brief Constructs an empty CalcOptions instance.
134 */
135 456 CalcOptions::CalcOptions(QObject *parent)
136
2/4
✓ Branch 2 taken 456 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 456 times.
✗ Branch 6 not taken.
456 : QObject(parent), mp_indexRangeCollection(new IndexRangeCollection(this))
137 {
138 456 }
139
140 /*!
141 \brief Constructs a CalcOptions instance.
142
143 All the members are initialized using the parameters:
144
145 \list
146 \li \a deepCalculation: m_deepCalculation (defaults to false)
147
148 \li \a mass_type: m_massType (defaults to Enums::MassType::BOTH)
149
150 \li \a capping: m_capType (defaults to Enums::CapType::BOTH)
151
152 \li \a monomer_entities The monomer entities to be accounted for in the
153 calculations (defaults to Enums::ChemicalEntity::NONE)
154
155 \li \a polymer_entities: The polymer entities to be accounted for in the
156 calculations (defaults to Enums::ChemicalEntity::NONE)
157 \endlist
158
159 The selection type is set by default to Oligomer (not residual chain).
160 */
161 192 CalcOptions::CalcOptions(bool deepCalculation,
162 Enums::MassType mass_type,
163 Enums::CapType capping,
164 Enums::ChemicalEntity monomer_entities,
165 Enums::ChemicalEntity polymer_entities,
166 192 QObject *parent)
167 : QObject(parent),
168 192 m_deepCalculation(deepCalculation),
169 192 m_massType(mass_type),
170 192 m_capType(capping),
171 192 m_monomerEntities(monomer_entities),
172 192 m_polymerEntities(polymer_entities),
173
2/4
✓ Branch 2 taken 192 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 192 times.
✗ Branch 6 not taken.
192 mp_indexRangeCollection(new IndexRangeCollection(this))
174 {
175 192 }
176
177 /*!
178 \brief Construct a CalcOptions instance as a copy of \a other.
179 */
180 10455 CalcOptions::CalcOptions(const CalcOptions &other, QObject *parent)
181 : QObject(parent),
182 10455 m_deepCalculation(other.m_deepCalculation),
183 10455 m_massType(other.m_massType),
184 10455 m_capType(other.m_capType),
185 10455 m_monomerEntities(other.m_monomerEntities),
186 10455 m_polymerEntities(other.m_polymerEntities),
187 10455 m_selectionType(other.m_selectionType),
188 10455 mp_indexRangeCollection(
189
2/4
✓ Branch 2 taken 10455 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10455 times.
✗ Branch 6 not taken.
10455 new IndexRangeCollection(*other.mp_indexRangeCollection, this))
190 {
191 10455 qDebug()
192 << "In pseudo copy constructor, other IndexRangeCollection indices as text:"
193 << other.getIndexRangeCollectionCstRef().indicesAsText();
194
195 // mp_indexRangeCollection = new IndexRangeCollection(this);
196 //
197 // foreach(const IndexRange *item,
198 // other.getIndexRangeCollectionCstRef().getRangesCstRef())
199 // mp_indexRangeCollection->appendIndexRange(*item);
200
201 10455 qDebug().noquote()
202 << "After pseudo copy constructor, with other calc options:"
203 << other.toString() << "\n this calc options:" << this->toString();
204 10455 }
205
206 /*!
207 \brief Returns a reference to this CalcOptions after having initialized it using
208 \a other.
209 */
210 CalcOptions &
211 66 CalcOptions::initialize(const CalcOptions &other)
212 {
213
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if(this == &other)
214 return *this;
215
216 66 m_deepCalculation = other.m_deepCalculation;
217 66 m_massType = other.m_massType;
218 66 m_capType = other.m_capType;
219 66 m_monomerEntities = other.m_monomerEntities;
220 66 m_polymerEntities = other.m_polymerEntities;
221 66 m_selectionType = other.m_selectionType;
222
223 132 mp_indexRangeCollection->setIndexRanges(
224 66 other.mp_indexRangeCollection->getRangesCstRef());
225
226 66 return *this;
227 }
228
229 /*!
230 \brief Returns an newly allocated CalcOptions instance with parent set to \a
231 parent.
232 */
233 CalcOptions *
234 3 CalcOptions::clone(QObject *parent)
235 {
236
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 CalcOptions *copy_p = new CalcOptions(parent);
237 3 copy_p->initialize(*this);
238 3 return copy_p;
239 }
240
241 /*!
242 \ b*rief Returns an newly allocated CalcOptions instance initialized using \a
243 other and with parent set to \a parent.
244 */
245 CalcOptions *
246 3 CalcOptions::clone(const CalcOptions &other, QObject *parent)
247 {
248
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 CalcOptions *copy_p = new CalcOptions(parent);
249 3 copy_p->initialize(other);
250 3 return copy_p;
251 }
252
253 /*!
254 \brief Destructs this CalcOptions object.
255
256 Clear the member coordinateList.
257 */
258 22548 CalcOptions::~CalcOptions()
259 {
260 22548 }
261
262 /*!
263 \brief Sets to \a deep the configuration defining if the mass calculations must
264 involve the recalculation of the masses of all the monomers.
265
266 The deep calculation is typically requested when computing masses involving
267 Monomer instance that might be modified with Modif instances.
268
269 \sa m_deepCalculation
270 */
271 void
272 57 CalcOptions::setDeepCalculation(bool deep)
273 {
274 57 m_deepCalculation = deep;
275 57 }
276
277 /*!
278 \brief Returns if the calculation should be deep.
279
280 \sa m_deepCalculation
281 */
282 bool
283 56322 CalcOptions::isDeepCalculation() const
284 {
285 56322 return m_deepCalculation;
286 }
287
288 /*!
289 \brief Copies \a index_range to the member IndexRangeCollection instance.
290
291 \note The IndexRangeCollection instance is first emptied, making index_range
292 essentially replacing its contents with a copy of \a index_range.
293 */
294 void
295 2397 CalcOptions::setIndexRange(const IndexRange &index_range)
296 {
297
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
2397 mp_indexRangeCollection->setIndexRange(index_range);
298 2397 }
299
300 /*!
301 \brief Creates an IndexRange instance with \a index_start and \a index_end and
302 sets it as the sole member of the member IndexRangeCollection instance.
303 */
304 void
305 2229 CalcOptions::setIndexRange(qsizetype index_start, qsizetype index_end)
306 {
307
1/2
✓ Branch 2 taken 2229 times.
✗ Branch 3 not taken.
2229 setIndexRange(IndexRange(index_start, index_end));
308 2229 }
309
310 /*!
311 \brief Allocates a copy of each IndexRange instance in the \a index_ranges
312 container and adds it to the member IndexRangeCollection instance.
313
314 \note The IndexRangeCollection instance is first emptied, essentially replacing
315 its contents with a copy of those in \a index_ranges.
316 */
317 void
318 24 CalcOptions::setIndexRanges(const IndexRangeCollection &index_ranges)
319 {
320 24 mp_indexRangeCollection->setIndexRanges(index_ranges);
321 24 }
322
323 /*!
324 \brief Returns a const reference to the member IndexRangeCollection instance.
325 */
326 const IndexRangeCollection &
327 15612 CalcOptions::getIndexRangeCollectionCstRef() const
328 {
329 15612 return *mp_indexRangeCollection;
330 }
331
332 /*!
333 \brief Returns a reference to the member IndexRangeCollection instance.
334 */
335 IndexRangeCollection &
336 240 CalcOptions::getIndexRangeCollectionRef()
337 {
338 240 return *mp_indexRangeCollection;
339 }
340
341 /*!
342 \brief Returns a reference to the member IndexRangeCollection instance.
343 */
344 IndexRangeCollection *
345 CalcOptions::getIndexRangeCollection()
346 {
347 return mp_indexRangeCollection;
348 }
349
350 /*!
351 \brief Sets the mass type to \a mass_type.
352
353 \sa m_massType
354 */
355 void
356 21 CalcOptions::setMassType(Enums::MassType mass_type)
357 {
358 21 m_massType = mass_type;
359 21 }
360
361 /*!
362 \brief Returns the mass type.
363
364 \sa m_massType
365 */
366 Enums::MassType
367 18 CalcOptions::getMassType() const
368 {
369 18 return m_massType;
370 }
371
372 /*!
373 \brief Set the selection type to \a selection_type.
374
375 \sa m_selectionType
376 */
377 void
378 21 CalcOptions::setSelectionType(Enums::SelectionType selection_type)
379 {
380 21 m_selectionType = selection_type;
381 21 }
382
383 /*!
384 \brief Returns the selection type.
385
386 \sa m_selectionType
387 */
388 Enums::SelectionType
389 5505 CalcOptions::getSelectionType() const
390 {
391 5505 return m_selectionType;
392 }
393
394 /*!
395 \brief Sets the cap type to \a cap_type.
396
397 \sa m_capType
398 */
399 void
400 654 CalcOptions::setCapType(Enums::CapType cap_type)
401 {
402 654 m_capType = cap_type;
403 654 }
404
405 /*!
406 \brief Returns the cap type.
407
408 \sa m_capType
409 */
410 Enums::CapType
411 5856 CalcOptions::getCapType() const
412 {
413 5856 return m_capType;
414 }
415
416 /*!
417 \brief Sets the monomer entities to \a monomer_chem_ent.
418
419 \sa m_monomerEntities
420 */
421 void
422 1581 CalcOptions::setMonomerEntities(Enums::ChemicalEntity monomer_chem_ent)
423 {
424 1581 m_monomerEntities = monomer_chem_ent;
425 1581 }
426
427 /*!
428 \brief Returns the monomer entities.
429
430 \sa m_monomerEntities
431 */
432 Enums::ChemicalEntity
433 36402 CalcOptions::getMonomerEntities() const
434 {
435 36402 return m_monomerEntities;
436 }
437
438 /*!
439 \brief Sets the polymer entities to \a polymer_chem_ent.
440
441 \sa m_polymerEntities
442 */
443 void
444 30 CalcOptions::setPolymerEntities(Enums::ChemicalEntity polymer_chem_ent)
445 {
446 30 m_polymerEntities = polymer_chem_ent;
447 30 }
448
449 /*!
450 \brief Returns the polymer entities.
451
452 \sa m_polymerEntities
453 */
454 Enums::ChemicalEntity
455 6480 CalcOptions::getPolymerEntities() const
456 {
457 6480 return m_polymerEntities;
458 }
459
460 /*!
461 \brief Returns true if this instance is identical to \a other, false otherwise.
462 */
463 bool
464 15 CalcOptions::operator==(const CalcOptions &other) const
465 {
466
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if(m_deepCalculation != other.m_deepCalculation ||
467
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 m_massType != other.m_massType || m_capType != other.m_capType ||
468 m_monomerEntities != other.m_monomerEntities ||
469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 m_polymerEntities != other.m_polymerEntities ||
470 m_selectionType != other.m_selectionType)
471 return false;
472
473
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
15 if(mp_indexRangeCollection->size() != other.mp_indexRangeCollection->size())
474 return false;
475
476
2/2
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 15 times.
42 for(qsizetype iter = 0; iter < mp_indexRangeCollection->size(); ++iter)
477
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
27 if(mp_indexRangeCollection->getRangeCstRefAt(iter) !=
478 27 other.mp_indexRangeCollection->getRangeCstRefAt(iter))
479 return false;
480
481 return true;
482 }
483
484 /*!
485 \brief Returns true if this instance is different than \a other, false
486 otherwise.
487 */
488 bool
489 6 CalcOptions::operator!=(const CalcOptions &other) const
490 {
491 6 return !operator==(other);
492 }
493
494 /*!
495 \brief Returns a string describing this CalcOptions instance.
496 */
497 QString
498 3 CalcOptions::toString() const
499 {
500 // qDebug() << "\n~~~~~~~~~~~~~~ CalcOptions instance ~~~~~~~~~~~~~\n"
501 // << this << "\n"
502 // << "m_deepCalculation:" << m_deepCalculation
503 // << "\n m_massType:" << massTypeMap[m_massType]
504 // << "\n m_capType:" << capTypeMap[m_capType] << "\n ";
505
506 3 QString text;
507
508
3/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
3 text += QString("m_deepCalculation: %1\n").arg(m_deepCalculation);
509
3/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
6 text += QString("m_massType: %1\n").arg(massTypeMap[m_massType]);
510
3/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
6 text += QString("m_capType: %1\n").arg(capTypeMap[m_capType]);
511
512
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 if(!mp_indexRangeCollection->getRangesCstRef().size())
513 text += "No IndexRange instances\n";
514 else
515
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 text += QString("IndexRange instances (%1 instance(s)):\n")
516
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 .arg(mp_indexRangeCollection->getRangesCstRef().size());
517
518
3/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 3 times.
12 foreach(const IndexRange *item, mp_indexRangeCollection->getRangesCstRef())
519 {
520
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 text += QString("[%1 - %2]\n").arg(item->m_start).arg(item->m_stop);
521 }
522
523
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 text += QString("%1: %2\n")
524
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 .arg("Monomer chemical entities")
525
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 .arg(chemicalEntityMap[m_monomerEntities]);
526
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 text += QString("%1: %2\n")
527
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 .arg("Polymer chemical entities")
528
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 .arg(chemicalEntityMap[m_polymerEntities]);
529
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 text += QString("%1: %2\n")
530
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 .arg("Selection type")
531
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 .arg(selectionTypeMap[m_selectionType]);
532
533 3 return text;
534 }
535
536 void
537 CalcOptions::registerJsConstructor(QJSEngine *engine)
538 {
539 if(!engine)
540 {
541 qWarning() << "Cannot register CalcOptions class: engine is null";
542 return;
543 }
544
545 // Register the meta object as a constructor
546
547 QJSValue jsMetaObject =
548 engine->newQMetaObject(&CalcOptions::staticMetaObject);
549 engine->globalObject().setProperty("CalcOptions", jsMetaObject);
550 }
551
552
553 } // namespace libXpertMassCore
554 } // namespace MsXpS
555