libpappsomspp
Library for mass spectrometry
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 "utils.h"
37#include "types.h"
39#include "trace/trace.h"
40
41
42namespace pappso
43{
44
45
46QRegularExpression Utils::xyMassDataFormatRegExp =
47 QRegularExpression("^(\\d*\\.?\\d+)([^\\d^\\.^-]+)(-?\\d*\\.?\\d*[e-]?\\d*)");
48
49QRegularExpression Utils::endOfLineRegExp = QRegularExpression("^\\s+$");
50
51const QString
53{
54 int size = log10(num);
55 size += 97;
56 QLatin1Char latin1_char(size);
57 QString base(latin1_char);
58 base.append(QString().setNum(num));
59 return (base);
60}
61
62
63void
64Utils::writeLexicalOrderedString(QTextStream *p_out, unsigned int num)
65{
66 *p_out << (char)(log10(num) + 97) << num;
67}
68
69
70//! Determine the number of zero decimals between the decimal point and the
71//! first non-zero decimal.
72/*!
73 * 0.11 would return 0 (no empty decimal)
74 * 2.001 would return 2
75 * 1000.0001254 would return 3
76 *
77 * \param value the value to be analyzed
78 * \return the number of '0' decimals between the decimal separator '.' and
79 * the first non-0 decimal
80 */
81int
83{
84 //qDebug() << qSetRealNumberPrecision(10) << "Double value: " << value;
85
86 int intPart = static_cast<int>(value);
87
88 //qDebug() << "int part:" << intPart;
89
90 double decimalPart = value - intPart;
91
92 //qDebug() << qSetRealNumberPrecision(10) << "decimal part: " << decimalPart;
93
94 int count = 0;
95
96 while(decimalPart > 0)
97 {
98 ++count;
99
100 decimalPart *= 10;
101
102 //qDebug() << "Iteration " << count << "decimal part:" << decimalPart;
103
104 if(decimalPart >= 1)
105 {
106 //qDebug() << "Because decimal part " << decimalPart
107 //<< "is >= 1, breaking loop while count is " << count << ".";
108
109 break;
110 }
111 }
112
113 //qDebug() << "Returning count:" << count;
114
115 return count;
116}
117
118
120Utils::roundToDecimals(pappso_double value, int decimal_places)
121{
122 if(decimal_places < 0)
123 return value;
124
125 return ceil((value * pow(10, decimal_places)) - 0.49) /
126 pow(10, decimal_places);
127}
128
129
130long long int
132{
133 pappso::pappso_double test_decimal = 100000000000;
134 if(sizeof(int *) == 4)
135 { // 32bits
136 test_decimal = 100000000;
137 }
138 return (floor(input * test_decimal));
139}
140
141
142std::string
143Utils::toUtf8StandardString(const QString &text)
144{
145 std::string env_backup = setlocale(LC_ALL, "");
146
147 // struct lconv *lc_backup = localeconv();
148 // qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()"
149 //<< "env_backup=" << env_backup.c_str() << "lc_backup->decimal_point"
150 //<< lc_backup->decimal_point;
151
152 // Force locale to be "C".
153 setlocale(LC_ALL, "C");
154
155 // Now perform the conversion.
156 QByteArray byte_array = text.toUtf8();
157 std::string stdText = "";
158
159 for(char c : byte_array)
160 {
161 stdText += c;
162 }
163
164 // Set back the locale to the backed-up one.
165 setlocale(LC_ALL, env_backup.c_str());
166
167 return stdText;
168}
169
170
171bool
172Utils::writeToFile(const QString &text, const QString &file_name)
173{
174
175 QFile file(file_name);
176
177 if(file.open(QFile::WriteOnly | QFile::Truncate))
178 {
179
180 QTextStream out(&file);
181
182 out << text;
183
184 out.flush();
185 file.close();
186
187 return true;
188 }
189
190 return false;
191}
192
193
194bool
195Utils::appendToFile(const QString &text, const QString &file_name)
196{
197
198 QFile file(file_name);
199
200 if(file.open(QFile::WriteOnly | QFile::Append))
201 {
202
203 QTextStream out(&file);
204
205 out << text;
206
207 out.flush();
208 file.close();
209
210 return true;
211 }
212
213 return false;
214}
215
216
217std::size_t
218Utils::extractScanNumberFromMzmlNativeId(const QString &spectrum_native_id)
219{
220 qDebug() << " " << spectrum_native_id;
221 QStringList native_id_list = spectrum_native_id.split("=");
222 if(native_id_list.size() < 2)
223 {
224 throw ExceptionNotFound(
225 QObject::tr("scan number not found in mzML native id %1")
226 .arg(spectrum_native_id));
227 }
228 else
229 {
230 /** TODO activate this in a future release to ensure scan number
231 for(auto i = 0; i < native_id_list.size(); i += 2)
232 {
233 if(native_id_list[i] == "scan")
234 {
235 return native_id_list[i + 1].toULong();
236 }
237 }
238
239 throw ExceptionNotFound(
240 QObject::tr("scan number not found in mzML native id %1")
241 .arg(spectrum_native_id));
242
243*/
244 return native_id_list.back().toULong();
245 }
246 return 0;
247}
248
249
250QString
251Utils::pointerToString(const void *const pointer)
252{
253 return QString("%1").arg(
254 (quintptr)pointer, QT_POINTER_SIZE * 2, 16, QChar('0'));
255}
256
257
258//! Tell if both double values, are equal within the double representation
259//! capabilities of the platform.
260bool
261Utils::almostEqual(double value1, double value2, int decimalPlaces)
262{
263 // QString value1String = QString("%1").arg(value1,
264 // 0, 'f', 60);
265 // QString value2String = QString("%1").arg(value2,
266 // 0, 'f', 60);
267
268 // qWarning() << __FILE__ << __LINE__ << __FUNCTION__
269 //<< "value1:" << value1String << "value2:" << value2String;
270
271 // The machine epsilon has to be scaled to the magnitude of the values used
272 // and multiplied by the desired precision in ULPs (units in the last place)
273 // (decimal places).
274
275 double valueSum = std::abs(value1 + value2);
276 // QString valueSumString = QString("%1").arg(valueSum,
277 // 0, 'f', 60);
278
279 double valueDiff = std::abs(value1 - value2);
280 // QString valueDiffString = QString("%1").arg(valueDiff,
281 // 0, 'f', 60);
282
283 double epsilon = std::numeric_limits<double>::epsilon();
284 // QString epsilonString = QString("%1").arg(epsilon,
285 // 0, 'f', 60);
286
287 double scaleFactor = epsilon * valueSum * decimalPlaces;
288 // QString scaleFactorString = QString("%1").arg(scaleFactor,
289 // 0, 'f', 60);
290
291 // qWarning() << "valueDiff:" << valueDiffString << "valueSum:" <<
292 // valueSumString <<
293 //"epsilon:" << epsilonString << "scaleFactor:" << scaleFactorString;
294
295 bool res = valueDiff < scaleFactor
296 // unless the result is subnormal:
297 || valueDiff < std::numeric_limits<double>::min();
298
299 // qWarning() << __FILE__ << __LINE__ << __FUNCTION__
300 //<< "returning res:" << res;
301
302 return res;
303}
304
305
306double
308{
309 return std::nextafter(value, value + 1);
310}
311
312
313QString
315 const QString &msg, std::chrono::system_clock::time_point chrono_time)
316{
317
318 time_t tt;
319
320 tt = std::chrono::system_clock::to_time_t(chrono_time);
321
322 QString debug_text =
323 QString("%1 - %2\n").arg(msg).arg(QString::fromLatin1(ctime(&tt)));
324
325 return debug_text;
326}
327
328
329QString
331 const QString &msg,
332 std::chrono::system_clock::time_point chrono_start,
333 std::chrono::system_clock::time_point chrono_finish)
334{
335 QString debug_text =
336 QString(
337 "%1 %2 min = %3 s = %4 ms = %5 "
338 "µs\n")
339 .arg(msg)
340 .arg(std::chrono::duration_cast<std::chrono::minutes>(chrono_finish -
341 chrono_start)
342 .count())
343 .arg(std::chrono::duration_cast<std::chrono::seconds>(chrono_finish -
344 chrono_start)
345 .count())
346 .arg(std::chrono::duration_cast<std::chrono::milliseconds>(chrono_finish -
347 chrono_start)
348 .count())
349 .arg(std::chrono::duration_cast<std::chrono::microseconds>(chrono_finish -
350 chrono_start)
351 .count());
352
353 return debug_text;
354}
355
356
357std::vector<double>
359 std::size_t &error_count)
360{
361
362 QStringList string_list =
363 text.split(QRegularExpression("[\\s]+"), Qt::SkipEmptyParts);
364
365 // qDebug() << "string list:" << string_list;
366
367 std::vector<double> double_vector;
368
369 for(int iter = 0; iter < string_list.size(); ++iter)
370 {
371 QString current_string = string_list.at(iter);
372
373 bool ok = false;
374
375 double current_double = current_string.toDouble(&ok);
376
377 if(!current_double && !ok)
378 {
379 ++error_count;
380 continue;
381 }
382
383 double_vector.push_back(current_double);
384 }
385
386 return double_vector;
387}
388
389
390std::vector<std::size_t>
392 std::size_t &error_count)
393{
394 // qDebug() << "Parsing text:" << text;
395
396 QStringList string_list =
397 text.split(QRegularExpression("[\\s]+"), Qt::SkipEmptyParts);
398
399 // qDebug() << "string list size:" << string_list.size()
400 //<< "values:" << string_list;
401
402 std::vector<std::size_t> sizet_vector;
403
404 for(int iter = 0; iter < string_list.size(); ++iter)
405 {
406 QString current_string = string_list.at(iter);
407
408 bool ok = false;
409
410 std::size_t current_sizet = current_string.toUInt(&ok);
411
412 if(!current_sizet && !ok)
413 {
414 ++error_count;
415 continue;
416 }
417
418 sizet_vector.push_back(current_sizet);
419 }
420
421 return sizet_vector;
422}
423QString
425{
426 if(value)
427 return "TRUE";
428 return "FALSE";
429}
430
431QString
433{
434
435 if(mz_format == MzFormat::mzML)
436 return "mzML";
437 else if(mz_format == MzFormat::mzXML)
438 return "mzXML";
439 else if(mz_format == MzFormat::MGF)
440 return "MGF";
441 else if(mz_format == MzFormat::SQLite3)
442 return "SQLite3";
443 else if(mz_format == MzFormat::xy)
444 return "xy";
445 else if(mz_format == MzFormat::mz5)
446 return "mz5";
447 else if(mz_format == MzFormat::msn)
448 return "msn";
449 else if(mz_format == MzFormat::abSciexWiff)
450 return "abSciexWiff";
451 else if(mz_format == MzFormat::abSciexT2D)
452 return "abSciexT2D";
453 else if(mz_format == MzFormat::agilentMassHunter)
454 return "agilentMassHunter";
455 else if(mz_format == MzFormat::thermoRaw)
456 return "thermoRaw";
457 else if(mz_format == MzFormat::watersRaw)
458 return "watersRaw";
459 else if(mz_format == MzFormat::brukerFid)
460 return "brukerFid";
461 else if(mz_format == MzFormat::brukerYep)
462 return "brukerYep";
463 else if(mz_format == MzFormat::brukerBaf)
464 return "brukerBaf";
465 else if(mz_format == MzFormat::brukerTims)
466 return "brukerTims";
467 else
468 return "unknown";
469}
470
471} // namespace pappso
static std::size_t extractScanNumberFromMzmlNativeId(const QString &spectrum_native_id)
Definition: utils.cpp:218
static QString chronoTimePointDebugString(const QString &msg, std::chrono::system_clock::time_point chrono_time=std::chrono::system_clock::now())
Definition: utils.cpp:314
static QString pointerToString(const void *const pointer)
Definition: utils.cpp:251
static pappso_double roundToDecimals(pappso_double value, int decimal_places)
Definition: utils.cpp:120
static bool almostEqual(double value1, double value2, int decimalPlaces=10)
Definition: utils.cpp:261
static std::vector< double > splitMzStringToDoubleVectorWithSpaces(const QString &text, std::size_t &error_count)
Definition: utils.cpp:358
static double nearestGreater(double value)
Definition: utils.cpp:307
static std::string toUtf8StandardString(const QString &text)
Definition: utils.cpp:143
static bool appendToFile(const QString &text, const QString &file_name)
Definition: utils.cpp:195
static QString booleanToString(bool value)
convenient function to transform a boolean to QString "TRUE" or "FALSE" QString returned is readable ...
Definition: utils.cpp:424
static QString mzFormatAsString(MzFormat mz_format)
Convenience function to return a string describing the MzFormat of a file.
Definition: utils.cpp:432
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:330
static bool writeToFile(const QString &text, const QString &file_name)
Definition: utils.cpp:172
static std::vector< std::size_t > splitSizetStringToSizetVectorWithSpaces(const QString &text, std::size_t &error_count)
Definition: utils.cpp:391
static QRegularExpression xyMassDataFormatRegExp
Definition: utils.h:53
static const QString getLexicalOrderedString(unsigned int num)
Definition: utils.cpp:52
static void writeLexicalOrderedString(QTextStream *p_out, unsigned int num)
Definition: utils.cpp:64
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:82
static QRegularExpression endOfLineRegExp
Regular expression that tracks the end of line in text files.
Definition: utils.h:62
static long long int roundToDecimal32bitsAsLongLongInt(pappso::pappso_double input)
Definition: utils.cpp:131
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition: aa.cpp:39
MzFormat
Definition: types.h:108
@ xy
(x,y) format
@ SQLite3
SQLite3 format.
@ MGF
Mascot format.
double pappso_double
A type definition for doubles.
Definition: types.h:49
This header contains all the type re-definitions and all the global variables definitions used in the...