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