##// END OF EJS Templates
Merge branch 'feature/AmdaV2' into develop
Merge branch 'feature/AmdaV2' into develop

File last commit:

r775:c9e284499782
r779:72250e9134d9 merge
Show More
AmdaResultParser.cpp
225 lines | 7.6 KiB | text/x-c | CppLexer
/ plugins / amda / src / AmdaResultParser.cpp
Alexandre Leroux
Amda provider (3)...
r380 #include "AmdaResultParser.h"
Alexandre Leroux
Passes TimeWidget in UTC...
r489 #include <Common/DateUtils.h>
Alexandre Leroux
Amda provider (3)...
r380 #include <Data/ScalarSeries.h>
Alexandre Leroux
Updates data series creation according to the value type (vector or scalar)
r565 #include <Data/VectorSeries.h>
Alexandre Leroux
Amda provider (3)...
r380
#include <QDateTime>
#include <QFile>
Alexandre Leroux
Reads x-axis unit in result file
r393 #include <QRegularExpression>
Alexandre Leroux
Amda provider (3)...
r380
Add the cmath include missing
r400 #include <cmath>
Alexandre Leroux
Amda provider (3)...
r380 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
namespace {
Alexandre Leroux
Handles "Not found" error for AMDA result parser
r446 /// Message in result file when the file was not found on server
const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found");
Alexandre Leroux
Improves controls when reading results
r394 /// Separator between values in a result line
const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
Alexandre Leroux
- Changes the way to retrieve unit in AMDA result file: The generated header in the result file differs from the first version...
r775 /// Regex to find the header of the data in the file. This header indicates the end of comments in
/// the file
const auto DATA_HEADER_REGEX = QRegularExpression{QStringLiteral("#\\s*DATA\\s*:")};
/// Format for dates in result files
const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
Alexandre Leroux
Reads x-axis unit in result file
r393 /// Regex to find unit in a line. Examples of valid lines:
Alexandre Leroux
- Changes the way to retrieve unit in AMDA result file: The generated header in the result file differs from the first version...
r775 /// ... PARAMETER_UNITS : nT ...
/// ... PARAMETER_UNITS:nT ...
/// ... PARAMETER_UNITS: m² ...
/// ... PARAMETER_UNITS : m/s ...
const auto UNIT_REGEX = QRegularExpression{QStringLiteral("\\s*PARAMETER_UNITS\\s*:\\s*(.+)")};
QDateTime dateTimeFromString(const QString &stringDate) noexcept
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
return QDateTime::fromString(stringDate, Qt::ISODateWithMs);
#else
return QDateTime::fromString(stringDate, DATE_FORMAT);
#endif
}
Alexandre Leroux
Reads x-axis unit in result file
r393
Alexandre Leroux
Improves controls when reading results
r394 /// Converts a string date to a double date
/// @return a double that represents the date in seconds, NaN if the string date can't be converted
Alexandre Leroux
Amda provider (3)...
r380 double doubleDate(const QString &stringDate) noexcept
{
Alexandre Leroux
- Changes the way to retrieve unit in AMDA result file: The generated header in the result file differs from the first version...
r775 // Format: yyyy-MM-ddThh:mm:ss.zzz
auto dateTime = dateTimeFromString(stringDate);
Alexandre Leroux
Passes TimeWidget in UTC...
r489 dateTime.setTimeSpec(Qt::UTC);
return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
Alexandre Leroux
Improves controls when reading results
r394 : std::numeric_limits<double>::quiet_NaN();
Alexandre Leroux
Amda provider (3)...
r380 }
Alexandre Leroux
Improves AMDA result parsing...
r492 /// Checks if a line is a comment line
bool isCommentLine(const QString &line)
{
return line.startsWith("#");
}
Alexandre Leroux
Updates method for reading results according to the value type (vector or scalar)
r564 /// @return the number of lines to be read depending on the type of value passed in parameter
int nbValues(AmdaResultParser::ValueType valueType) noexcept
{
switch (valueType) {
case AmdaResultParser::ValueType::SCALAR:
return 1;
case AmdaResultParser::ValueType::VECTOR:
return 3;
case AmdaResultParser::ValueType::UNKNOWN:
// Invalid case
break;
}
// Invalid cases
qCCritical(LOG_AmdaResultParser())
<< QObject::tr("Can't get the number of values to read: unsupported type");
return 0;
}
Alexandre Leroux
Reads x-axis unit in result file
r393 /**
* Reads stream to retrieve x-axis unit
* @param stream the stream to read
* @return the unit that has been read in the stream, a default unit (time unit with no label) if an
* error occured during reading
*/
Unit readXAxisUnit(QTextStream &stream)
{
QString line{};
Alexandre Leroux
- Changes the way to retrieve unit in AMDA result file: The generated header in the result file differs from the first version...
r775 // Searches unit in the comment lines (as long as the reading has not reached the data header)
while (stream.readLineInto(&line) && !line.contains(DATA_HEADER_REGEX)) {
Alexandre Leroux
Reads x-axis unit in result file
r393 auto match = UNIT_REGEX.match(line);
if (match.hasMatch()) {
return Unit{match.captured(1), true};
}
}
Alexandre Leroux
Improves AMDA result parsing...
r492 qCWarning(LOG_AmdaResultParser()) << QObject::tr("The unit could not be found in the file");
Alexandre Leroux
Reads x-axis unit in result file
r393 // Error cases
return Unit{{}, true};
}
Alexandre Leroux
Improves controls when reading results
r394 /**
* Reads stream to retrieve results
* @param stream the stream to read
* @return the pair of vectors x-axis data/values data that has been read in the stream
*/
Alexandre Leroux
Uses std::vector when retrieving Amda results
r733 std::pair<std::vector<double>, std::vector<double> >
Alexandre Leroux
Updates method for reading results according to the value type (vector or scalar)
r564 readResults(QTextStream &stream, AmdaResultParser::ValueType valueType)
Alexandre Leroux
Improves controls when reading results
r394 {
Alexandre Leroux
- Changes the way to retrieve unit in AMDA result file: The generated header in the result file differs from the first version...
r775 auto expectedNbValues = nbValues(valueType) + 1;
Alexandre Leroux
Updates method for reading results according to the value type (vector or scalar)
r564
Alexandre Leroux
Uses std::vector when retrieving Amda results
r733 auto xData = std::vector<double>{};
auto valuesData = std::vector<double>{};
Alexandre Leroux
Improves controls when reading results
r394
QString line{};
Alexandre Leroux
Improves AMDA result parsing...
r492
Alexandre Leroux
- Changes the way to retrieve unit in AMDA result file: The generated header in the result file differs from the first version...
r775 // Skip comment lines
while (stream.readLineInto(&line) && isCommentLine(line)) {
}
if (!stream.atEnd()) {
do {
Alexandre Leroux
Improves AMDA result parsing...
r492 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
Alexandre Leroux
- Changes the way to retrieve unit in AMDA result file: The generated header in the result file differs from the first version...
r775 if (lineData.size() == expectedNbValues) {
Alexandre Leroux
Improves AMDA result parsing...
r492 // X : the data is converted from date to double (in secs)
auto x = doubleDate(lineData.at(0));
Alexandre Leroux
Updates AMDA result parser to accept NaN values...
r496 // Adds result only if x is valid. Then, if value is invalid, it is set to NaN
if (!std::isnan(x)) {
Alexandre Leroux
Improves AMDA result parsing...
r492 xData.push_back(x);
Alexandre Leroux
Updates AMDA result parser to accept NaN values...
r496
Alexandre Leroux
Updates method for reading results according to the value type (vector or scalar)
r564 // Values
Alexandre Leroux
- Changes the way to retrieve unit in AMDA result file: The generated header in the result file differs from the first version...
r775 for (auto valueIndex = 1; valueIndex < expectedNbValues; ++valueIndex) {
auto column = valueIndex;
Alexandre Leroux
Updates method for reading results according to the value type (vector or scalar)
r564
bool valueOk;
auto value = lineData.at(column).toDouble(&valueOk);
if (!valueOk) {
qCWarning(LOG_AmdaResultParser())
<< QObject::tr(
"Value from (line %1, column %2) is invalid and will be "
"converted to NaN")
.arg(line, column);
value = std::numeric_limits<double>::quiet_NaN();
}
Alexandre Leroux
Uses std::vector when retrieving Amda results
r733 valuesData.push_back(value);
Alexandre Leroux
Updates AMDA result parser to accept NaN values...
r496 }
Alexandre Leroux
Improves AMDA result parsing...
r492 }
else {
qCWarning(LOG_AmdaResultParser())
Alexandre Leroux
Updates AMDA result parser to accept NaN values...
r496 << QObject::tr("Can't retrieve results from line %1: x is invalid")
Alexandre Leroux
Improves AMDA result parsing...
r492 .arg(line);
}
Alexandre Leroux
Improves controls when reading results
r394 }
else {
qCWarning(LOG_AmdaResultParser())
Alexandre Leroux
Improves AMDA result parsing...
r492 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
Alexandre Leroux
Improves controls when reading results
r394 }
Alexandre Leroux
- Changes the way to retrieve unit in AMDA result file: The generated header in the result file differs from the first version...
r775 } while (stream.readLineInto(&line));
Alexandre Leroux
Improves controls when reading results
r394 }
Alexandre Leroux
Uses std::vector when retrieving Amda results
r733 return std::make_pair(std::move(xData), std::move(valuesData));
Alexandre Leroux
Improves controls when reading results
r394 }
Alexandre Leroux
Amda provider (3)...
r380 } // namespace
Alexandre Leroux
Creates enum that represents the value types that can be read in AMDA...
r563 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath,
ValueType valueType) noexcept
Alexandre Leroux
Amda provider (3)...
r380 {
Alexandre Leroux
Creates enum that represents the value types that can be read in AMDA...
r563 if (valueType == ValueType::UNKNOWN) {
qCCritical(LOG_AmdaResultParser())
<< QObject::tr("Can't retrieve AMDA data: the type of values to be read is unknown");
return nullptr;
}
Alexandre Leroux
Amda provider (3)...
r380 QFile file{filePath};
if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
qCCritical(LOG_AmdaResultParser())
<< QObject::tr("Can't retrieve AMDA data from file %1: %2")
.arg(filePath, file.errorString());
return nullptr;
}
QTextStream stream{&file};
Alexandre Leroux
Handles "Not found" error for AMDA result parser
r446 // Checks if the file was found on the server
auto firstLine = stream.readLine();
if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0) {
qCCritical(LOG_AmdaResultParser())
<< QObject::tr("Can't retrieve AMDA data from file %1: file was not found on server")
.arg(filePath);
return nullptr;
}
Alexandre Leroux
Reads x-axis unit in result file
r393 // Reads x-axis unit
Alexandre Leroux
Improves AMDA result parsing...
r492 stream.seek(0); // returns to the beginning of the file
Alexandre Leroux
Reads x-axis unit in result file
r393 auto xAxisUnit = readXAxisUnit(stream);
// Reads results
Alexandre Leroux
Updates method for reading results according to the value type (vector or scalar)
r564 auto results = readResults(stream, valueType);
Alexandre Leroux
Updates data series creation according to the value type (vector or scalar)
r565 // Creates data series
switch (valueType) {
case ValueType::SCALAR:
Alexandre Leroux
Uses std::vector when retrieving Amda results
r733 return std::make_shared<ScalarSeries>(std::move(results.first),
std::move(results.second), xAxisUnit, Unit{});
case ValueType::VECTOR:
return std::make_shared<VectorSeries>(std::move(results.first),
std::move(results.second), xAxisUnit, Unit{});
Alexandre Leroux
Updates data series creation according to the value type (vector or scalar)
r565 case ValueType::UNKNOWN:
// Invalid case
break;
}
Alexandre Leroux
Amda provider (3)...
r380
Alexandre Leroux
Updates data series creation according to the value type (vector or scalar)
r565 // Invalid cases
qCCritical(LOG_AmdaResultParser())
<< QObject::tr("Can't create data series: unsupported value type");
return nullptr;
Alexandre Leroux
Amda provider (3)...
r380 }