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  QString base(size);
57  base.append(QString().setNum(num));
58  return (base);
59 }
60 
61 
62 void
63 Utils::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  */
80 int
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 
119 Utils::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 
129 long 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 
141 std::string
142 Utils::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 
170 bool
171 Utils::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 
193 bool
194 Utils::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 
216 std::size_t
217 Utils::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 
249 QString
250 Utils::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.
259 bool
260 Utils::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 
305 double
307 {
308  return std::nextafter(value, value + 1);
309 }
310 
311 
312 QString
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 
328 QString
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 
356 std::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 
389 std::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 }
422 QString
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...