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 
42 namespace pappso
43 {
44 
45 
46 QRegularExpression Utils::xyMassDataFormatRegExp =
47  QRegularExpression("^(\\d*\\.?\\d+)([^\\d^\\.^-]+)(-?\\d*\\.?\\d*[e-]?\\d*)");
48 
49 QRegularExpression Utils::endOfLineRegExp = QRegularExpression("^\\s+$");
50 
51 const 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 
63 void
64 Utils::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  */
81 int
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 
120 Utils::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 
130 long 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 
142 std::string
143 Utils::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 
171 bool
172 Utils::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 
194 bool
195 Utils::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 
217 std::size_t
218 Utils::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 
250 QString
251 Utils::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.
260 bool
261 Utils::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 
306 double
308 {
309  return std::nextafter(value, value + 1);
310 }
311 
312 
313 QString
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 
329 QString
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 
357 std::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 
390 std::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 }
423 QString
425 {
426  if(value)
427  return "TRUE";
428  return "FALSE";
429 }
430 
431 QString
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...