libpappsomspp
Library for mass spectrometry
Loading...
Searching...
No Matches
utils.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 * Copyright (c) 2015 Olivier Langella <Olivier.Langella@moulon.inra.fr>.
3 *
4 * This file is part of the PAPPSOms++ library.
5 *
6 * PAPPSOms++ is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * PAPPSOms++ is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with PAPPSOms++. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Contributors:
20 * Olivier Langella <Olivier.Langella@moulon.inra.fr> - initial API and
21 *implementation
22 ******************************************************************************/
23
24/////////////////////// StdLib includes
25#include <cmath>
26#include <iomanip>
27
28
29/////////////////////// Qt includes
30#include <QDebug>
31#include <QFile>
32#include <QTextStream>
33
34
35/////////////////////// Local includes
36#include "config.h"
37#include "utils.h"
38#include "types.h"
40#include "trace/trace.h"
41
42
43namespace pappso
44{
45
46// Matches a double (decimal value, that is, m/z
47// value)
49 QRegularExpression("\\d*\\.?\\d+");
50
51// Matches anything that is not digit, '.', or '-'
52// (that is, matches a separator
53QRegularExpression Utils::anythingButDigitDotDash =
54 QRegularExpression("[^\\d^\\.^-]+");
55
56// Matches a double (with exp notation
57// possibly) and also potentially a '-' sign. This is the intensity.
59 QRegularExpression("-?\\d*\\.?\\d*[e-]?\\d*");
60
61// Matches <number><separator><number>, that is: m/z<separator>intensity.
62QRegularExpression Utils::xyMassDataFormatRegExp =
63 // QRegularExpression("^(\\d*\\.?\\d+)([^\\d^\\.^-]+)(-?\\d*\\.?\\d*[e-]?\\d*)");
64 QRegularExpression(
65 QString("^(%1)(%2)(%3)")
67 .arg(Utils::anythingButDigitDotDash.pattern())
69
70
71QRegularExpression Utils::endOfLineRegExp = QRegularExpression("^\\s+$");
72
73const QString
75{
76 int size = log10(num);
77 size += 97;
78 QLatin1Char latin1_char(size);
79 QString base(latin1_char);
80 base.append(QString().setNum(num));
81 return (base);
82}
83
84
85void
86Utils::writeLexicalOrderedString(QTextStream *p_out, unsigned int num)
87{
88 *p_out << (char)(log10(num) + 97) << num;
89}
90
91
92//! Determine the number of zero decimals between the decimal point and the
93//! first non-zero decimal.
94/*!
95 * 0.11 would return 0 (no empty decimal)
96 * 2.001 would return 2
97 * 1000.0001254 would return 3
98 *
99 * \param value the value to be analyzed
100 * \return the number of '0' decimals between the decimal separator '.' and
101 * the first non-0 decimal
102 */
103int
105{
106 // qDebug() << qSetRealNumberPrecision(10) << "Double value: " << value;
107
108 int intPart = static_cast<int>(value);
109
110 // qDebug() << "int part:" << intPart;
111
112 double decimalPart = value - intPart;
113
114 // qDebug() << qSetRealNumberPrecision(10) << "decimal part: " << decimalPart;
115
116 int count = 0;
117
118 while(decimalPart > 0)
119 {
120 ++count;
121
122 decimalPart *= 10;
123
124 // qDebug() << "Iteration " << count << "decimal part:" << decimalPart;
125
126 if(decimalPart >= 1)
127 {
128 // qDebug() << "Because decimal part " << decimalPart
129 //<< "is >= 1, breaking loop while count is " << count << ".";
130
131 break;
132 }
133 }
134
135 // qDebug() << "Returning count:" << count - 1;
136
137 return count - 1;
138}
139
140
142Utils::roundToDecimals(pappso_double value, int decimal_places)
143{
144 if(decimal_places < 0)
145 return value;
146
147 return ceil((value * pow(10, decimal_places)) - 0.49) /
148 pow(10, decimal_places);
149}
150
151
152long long int
154{
155 pappso::pappso_double test_decimal = 100000000000;
156 if(sizeof(int *) == 4)
157 { // 32bits
158 test_decimal = 100000000;
159 }
160 return (floor(input * test_decimal));
161}
162
163
164std::string
165Utils::toUtf8StandardString(const QString &text)
166{
167 std::string env_backup;
168 try
169 {
170#ifdef MXE
171 // std::locale::global(std::locale("C")); // set locale to default locale
172 env_backup = std::setlocale(LC_ALL, nullptr);
173 std::setlocale(LC_ALL, "C");
174#else
175 std::locale::global(std::locale("C")); // set locale to default locale
176#endif
177 }
178 catch(std::exception &error)
179 {
181 QObject::tr("Error trying to set local to C : %1").arg(error.what()));
182 }
183 // Now perform the conversion.
184 QByteArray byte_array = text.toUtf8();
185 std::string stdText = "";
186
187 for(char c : byte_array)
188 {
189 stdText += c;
190 }
191
192 try
193 {
194#ifdef MXE
195 // std::locale::global(std::locale("C")); // set locale to default locale
196 std::setlocale(LC_ALL, env_backup.c_str());
197#else // Set back the locale to the backed-up one.
198 std::locale::global(
199 std::locale("")); // sets locale according to OS environment
200#endif
201 }
202 catch(std::exception &error)
203 {
204
206 QObject::tr("Error trying to set local to original system one %1 : %2")
207 .arg(env_backup.c_str())
208 .arg(error.what()));
209 }
210
211 return stdText;
212}
213
214
215bool
216Utils::writeToFile(const QString &text, const QString &file_name)
217{
218
219 QFile file(file_name);
220
221 if(file.open(QFile::WriteOnly | QFile::Truncate))
222 {
223
224 QTextStream out(&file);
225
226 out << text;
227
228 out.flush();
229 file.close();
230
231 return true;
232 }
233
234 return false;
235}
236
237
238bool
239Utils::appendToFile(const QString &text, const QString &file_name)
240{
241
242 QFile file(file_name);
243
244 if(file.open(QFile::WriteOnly | QFile::Append))
245 {
246
247 QTextStream out(&file);
248
249 out << text;
250
251 out.flush();
252 file.close();
253
254 return true;
255 }
256
257 return false;
258}
259
260
261std::size_t
262Utils::extractScanNumberFromMzmlNativeId(const QString &spectrum_native_id)
263{
264 qDebug() << " " << spectrum_native_id;
265 QStringList native_id_list = spectrum_native_id.split("=");
266 if(native_id_list.size() < 2)
267 {
268 throw ExceptionNotFound(
269 QObject::tr("scan number not found in mzML native id %1")
270 .arg(spectrum_native_id));
271 }
272 else
273 {
274 /** TODO activate this in a future release to ensure scan number
275 for(auto i = 0; i < native_id_list.size(); i += 2)
276 {
277 if(native_id_list[i] == "scan")
278 {
279 return native_id_list[i + 1].toULong();
280 }
281 }
282
283 throw ExceptionNotFound(
284 QObject::tr("scan number not found in mzML native id %1")
285 .arg(spectrum_native_id));
286
287*/
288 return native_id_list.back().toULong();
289 }
290 return 0;
291}
292
293
294QString
295Utils::pointerToString(const void *const pointer)
296{
297 return QString("%1").arg(
298 (quintptr)pointer, QT_POINTER_SIZE * 2, 16, QChar('0'));
299}
300
301
302//! Tell if both double values, are equal within the double representation
303//! capabilities of the platform.
304bool
305Utils::almostEqual(double value1, double value2, int decimalPlaces)
306{
307 // QString value1String = QString("%1").arg(value1,
308 // 0, 'f', 60);
309 // QString value2String = QString("%1").arg(value2,
310 // 0, 'f', 60);
311
312 // qWarning() << __FILE__ << __LINE__ << __FUNCTION__
313 //<< "value1:" << value1String << "value2:" << value2String;
314
315 // The machine epsilon has to be scaled to the magnitude of the values used
316 // and multiplied by the desired precision in ULPs (units in the last place)
317 // (decimal places).
318
319 double valueSum = std::abs(value1 + value2);
320 // QString valueSumString = QString("%1").arg(valueSum,
321 // 0, 'f', 60);
322
323 double valueDiff = std::abs(value1 - value2);
324 // QString valueDiffString = QString("%1").arg(valueDiff,
325 // 0, 'f', 60);
326
327 double epsilon = std::numeric_limits<double>::epsilon();
328 // QString epsilonString = QString("%1").arg(epsilon,
329 // 0, 'f', 60);
330
331 double scaleFactor = epsilon * valueSum * decimalPlaces;
332 // QString scaleFactorString = QString("%1").arg(scaleFactor,
333 // 0, 'f', 60);
334
335 // qWarning() << "valueDiff:" << valueDiffString << "valueSum:" <<
336 // valueSumString <<
337 //"epsilon:" << epsilonString << "scaleFactor:" << scaleFactorString;
338
339 bool res = valueDiff < scaleFactor
340 // unless the result is subnormal:
341 || valueDiff < std::numeric_limits<double>::min();
342
343 // qWarning() << __FILE__ << __LINE__ << __FUNCTION__
344 //<< "returning res:" << res;
345
346 return res;
347}
348
349
350double
352{
353 return std::nextafter(value, value + 1);
354}
355
356
357QString
359 const QString &msg, std::chrono::system_clock::time_point chrono_time)
360{
361
362 time_t tt;
363
364 tt = std::chrono::system_clock::to_time_t(chrono_time);
365
366 QString debug_text =
367 QString("%1 - %2\n").arg(msg).arg(QString::fromLatin1(ctime(&tt)));
368
369 return debug_text;
370}
371
372
373QString
375 const QString &msg,
376 std::chrono::system_clock::time_point chrono_start,
377 std::chrono::system_clock::time_point chrono_finish)
378{
379 QString debug_text =
380 QString(
381 "%1 %2 min = %3 s = %4 ms = %5 "
382 "µs\n")
383 .arg(msg)
384 .arg(std::chrono::duration_cast<std::chrono::minutes>(chrono_finish -
385 chrono_start)
386 .count())
387 .arg(std::chrono::duration_cast<std::chrono::seconds>(chrono_finish -
388 chrono_start)
389 .count())
390 .arg(std::chrono::duration_cast<std::chrono::milliseconds>(chrono_finish -
391 chrono_start)
392 .count())
393 .arg(std::chrono::duration_cast<std::chrono::microseconds>(chrono_finish -
394 chrono_start)
395 .count());
396
397 return debug_text;
398}
399
400
401std::vector<double>
403 std::size_t &error_count)
404{
405
406 QStringList string_list =
407 text.split(QRegularExpression("[\\s]+"), Qt::SkipEmptyParts);
408
409 // qDebug() << "string list:" << string_list;
410
411 std::vector<double> double_vector;
412
413 for(int iter = 0; iter < string_list.size(); ++iter)
414 {
415 QString current_string = string_list.at(iter);
416
417 bool ok = false;
418
419 double current_double = current_string.toDouble(&ok);
420
421 if(!current_double && !ok)
422 {
423 ++error_count;
424 continue;
425 }
426
427 double_vector.push_back(current_double);
428 }
429
430 return double_vector;
431}
432
433
434std::vector<std::size_t>
436 std::size_t &error_count)
437{
438 // qDebug() << "Parsing text:" << text;
439
440 QStringList string_list =
441 text.split(QRegularExpression("[\\s]+"), Qt::SkipEmptyParts);
442
443 // qDebug() << "string list size:" << string_list.size()
444 //<< "values:" << string_list;
445
446 std::vector<std::size_t> sizet_vector;
447
448 for(int iter = 0; iter < string_list.size(); ++iter)
449 {
450 QString current_string = string_list.at(iter);
451
452 bool ok = false;
453
454 std::size_t current_sizet = current_string.toUInt(&ok);
455
456 if(!current_sizet && !ok)
457 {
458 ++error_count;
459 continue;
460 }
461
462 sizet_vector.push_back(current_sizet);
463 }
464
465 return sizet_vector;
466}
467QString
469{
470 if(value)
471 return "TRUE";
472 return "FALSE";
473}
474
475QString
477{
478
479 if(mz_format == MsDataFormat::mzML)
480 return "mzML";
481 else if(mz_format == MsDataFormat::mzXML)
482 return "mzXML";
483 else if(mz_format == MsDataFormat::MGF)
484 return "MGF";
485 else if(mz_format == MsDataFormat::SQLite3)
486 return "SQLite3";
487 else if(mz_format == MsDataFormat::xy)
488 return "xy";
489 else if(mz_format == MsDataFormat::mz5)
490 return "mz5";
491 else if(mz_format == MsDataFormat::msn)
492 return "msn";
493 else if(mz_format == MsDataFormat::abSciexWiff)
494 return "abSciexWiff";
495 else if(mz_format == MsDataFormat::abSciexT2D)
496 return "abSciexT2D";
497 else if(mz_format == MsDataFormat::agilentMassHunter)
498 return "agilentMassHunter";
499 else if(mz_format == MsDataFormat::thermoRaw)
500 return "thermoRaw";
501 else if(mz_format == MsDataFormat::watersRaw)
502 return "watersRaw";
503 else if(mz_format == MsDataFormat::brukerFid)
504 return "brukerFid";
505 else if(mz_format == MsDataFormat::brukerYep)
506 return "brukerYep";
507 else if(mz_format == MsDataFormat::brukerBaf)
508 return "brukerBaf";
509 else if(mz_format == MsDataFormat::brukerTims)
510 return "brukerTims";
511 else if(mz_format == MsDataFormat::brukerBafAscii)
512 return "brukerBafAscii";
513 else
514 return "unknown";
515}
516
517
518QString
520{
521
522 if(file_reader_type == FileReaderType::pwiz)
523 return "pwiz";
524 else if(file_reader_type == FileReaderType::xy)
525 return "xy";
526 else if(file_reader_type == FileReaderType::tims)
527 return "tims";
528 else if(file_reader_type == FileReaderType::tims_frames)
529 return "tims_frames";
530 else
531 return "unknown";
532}
533
534QString
536{
537 switch(type)
538 {
540 return "AL";
541 break;
543 return "NA";
544 break;
546 return "RA";
547 break;
548 default:
549 return "ER";
550 }
551}
552
553QString
555{
556 switch(type)
557 {
559 return "both";
560 break;
562 return "native";
563 break;
565 return "symmetric";
566 break;
567 default:
568 return "synthetic";
569 }
570}
571
572QString
574{
575 QString version(PAPPSOMSPP_VERSION);
576 return version;
577}
578} // namespace pappso
static std::size_t extractScanNumberFromMzmlNativeId(const QString &spectrum_native_id)
Definition utils.cpp:262
static QString chronoTimePointDebugString(const QString &msg, std::chrono::system_clock::time_point chrono_time=std::chrono::system_clock::now())
Definition utils.cpp:358
static QString toString(specglob::SpectralAlignmentType type)
Convenience function to return a string describing the specglob alingment type.
Definition utils.cpp:535
static QString pointerToString(const void *const pointer)
Definition utils.cpp:295
static pappso_double roundToDecimals(pappso_double value, int decimal_places)
Definition utils.cpp:142
static QRegularExpression anythingButDigitDotDash
Definition utils.h:54
static bool almostEqual(double value1, double value2, int decimalPlaces=10)
Definition utils.cpp:305
static QString msDataFormatAsString(MsDataFormat mz_format)
Convenience function to return a string describing the MzFormat of a file.
Definition utils.cpp:476
static std::vector< double > splitMzStringToDoubleVectorWithSpaces(const QString &text, std::size_t &error_count)
Definition utils.cpp:402
static double nearestGreater(double value)
Definition utils.cpp:351
static std::string toUtf8StandardString(const QString &text)
Definition utils.cpp:165
static bool appendToFile(const QString &text, const QString &file_name)
Definition utils.cpp:239
static QString booleanToString(bool value)
convenient function to transform a boolean to QString "TRUE" or "FALSE" QString returned is readable ...
Definition utils.cpp:468
static QString chronoIntervalDebugString(const QString &msg, std::chrono::system_clock::time_point chrono_start, std::chrono::system_clock::time_point chrono_finish=std::chrono::system_clock::now())
Definition utils.cpp:374
static bool writeToFile(const QString &text, const QString &file_name)
Definition utils.cpp:216
static std::vector< std::size_t > splitSizetStringToSizetVectorWithSpaces(const QString &text, std::size_t &error_count)
Definition utils.cpp:435
static QRegularExpression signedDoubleNumberExponentialRegExp
Definition utils.h:55
static QRegularExpression xyMassDataFormatRegExp
Definition utils.h:59
static QRegularExpression unsignedDoubleNumberNoExponentialRegExp
Definition utils.h:53
static const QString getLexicalOrderedString(unsigned int num)
Definition utils.cpp:74
static void writeLexicalOrderedString(QTextStream *p_out, unsigned int num)
Definition utils.cpp:86
static int zeroDecimalsInValue(pappso_double value)
0.11 would return 0 (no empty decimal) 2.001 would return 2 1000.0001254 would return 3
Definition utils.cpp:104
static QString fileReaderTypeAsString(FileReaderType file_reader_type)
Definition utils.cpp:519
static QRegularExpression endOfLineRegExp
Regular expression that tracks the end of line in text files.
Definition utils.h:68
static long long int roundToDecimal32bitsAsLongLongInt(pappso::pappso_double input)
Definition utils.cpp:153
static QString getVersion()
Definition utils.cpp:573
@ nonAlign
the type of alignment to put in origin matrix NON Alignment (0 - NA)
ExperimentalSpectrumDataPointType
Definition types.h:78
@ both
both, the ion and the complement exists in the original spectrum
@ symmetric
new peak : computed symmetric mass from a corresponding native peak
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition aa.cpp:39
MsDataFormat
Definition types.h:120
@ xy
(x,y) format
@ SQLite3
SQLite3 format.
@ MGF
Mascot format.
double pappso_double
A type definition for doubles.
Definition types.h:50
FileReaderType
Definition types.h:147
@ pwiz
using libpwizlite
@ tims
TimsMsRunReader : each scan is returned as a mass spectrum.
This header contains all the type re-definitions and all the global variables definitions used in the...