mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#3320 Observed data import. Line based CSV import
This commit is contained in:
@@ -184,7 +184,7 @@ std::vector<RimAsciiDataCurve*> RicPasteAsciiDataToSummaryPlotFeature::parseCurv
|
|||||||
if (col->dataType != Column::NUMERIC) continue;
|
if (col->dataType != Column::NUMERIC) continue;
|
||||||
|
|
||||||
RimAsciiDataCurve* curve = new RimAsciiDataCurve();
|
RimAsciiDataCurve* curve = new RimAsciiDataCurve();
|
||||||
curve->setTimeSteps(parser.dateTimeColumn()->dateTimeValues);
|
curve->setTimeSteps(parser.dateTimeColumn()->qDateTimeValues());
|
||||||
curve->setValues(parser.columnInfo(i)->values);
|
curve->setValues(parser.columnInfo(i)->values);
|
||||||
if (curvePrefix.isEmpty())
|
if (curvePrefix.isEmpty())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -188,11 +188,18 @@ RicPasteAsciiDataToSummaryPlotFeatureUi::RicPasteAsciiDataToSummaryPlotFeatureUi
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void RicPasteAsciiDataToSummaryPlotFeatureUi::setUiModeImport(const QString& fileName)
|
void RicPasteAsciiDataToSummaryPlotFeatureUi::setUiModeImport(const QString& fileName)
|
||||||
{
|
{
|
||||||
m_uiMode = UI_MODE_IMPORT;
|
|
||||||
|
|
||||||
m_parser = std::unique_ptr<RifCsvUserDataParser>(new RifCsvUserDataFileParser(fileName));
|
m_parser = std::unique_ptr<RifCsvUserDataParser>(new RifCsvUserDataFileParser(fileName));
|
||||||
|
|
||||||
|
if (m_parser->determineCsvLayout() != RifCsvUserDataParser::LineBased)
|
||||||
|
{
|
||||||
|
m_uiMode = UI_MODE_IMPORT;
|
||||||
initialize(m_parser.get());
|
initialize(m_parser.get());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_uiMode = UI_MODE_SILENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
@@ -205,6 +212,14 @@ void RicPasteAsciiDataToSummaryPlotFeatureUi::setUiModePasteText(const QString&
|
|||||||
initialize(m_parser.get());
|
initialize(m_parser.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RicPasteAsciiDataToSummaryPlotFeatureUi::UiMode RicPasteAsciiDataToSummaryPlotFeatureUi::uiModeImport() const
|
||||||
|
{
|
||||||
|
return m_uiMode;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ public:
|
|||||||
{
|
{
|
||||||
UI_MODE_NONE,
|
UI_MODE_NONE,
|
||||||
UI_MODE_IMPORT,
|
UI_MODE_IMPORT,
|
||||||
UI_MODE_PASTE
|
UI_MODE_PASTE,
|
||||||
|
UI_MODE_SILENT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DecimalSeparator
|
enum DecimalSeparator
|
||||||
@@ -123,6 +124,7 @@ public:
|
|||||||
void setUiModeImport(const QString& fileName);
|
void setUiModeImport(const QString& fileName);
|
||||||
void setUiModePasteText(const QString& text);
|
void setUiModePasteText(const QString& text);
|
||||||
|
|
||||||
|
UiMode uiModeImport() const;
|
||||||
const AsciiDataParseOptions parseOptions() const;
|
const AsciiDataParseOptions parseOptions() const;
|
||||||
void createNewPlot();
|
void createNewPlot();
|
||||||
|
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ RifCsvUserData::~RifCsvUserData()
|
|||||||
bool RifCsvUserData::parse(const QString& fileName, const AsciiDataParseOptions& parseOptions, QString* errorText)
|
bool RifCsvUserData::parse(const QString& fileName, const AsciiDataParseOptions& parseOptions, QString* errorText)
|
||||||
{
|
{
|
||||||
m_allResultAddresses.clear();
|
m_allResultAddresses.clear();
|
||||||
m_timeSteps.clear();
|
|
||||||
m_mapFromAddressToTimeStepIndex.clear();
|
|
||||||
m_mapFromAddressToResultIndex.clear();
|
m_mapFromAddressToResultIndex.clear();
|
||||||
|
|
||||||
m_parser = std::unique_ptr<RifCsvUserDataFileParser>(new RifCsvUserDataFileParser(fileName, errorText));
|
m_parser = std::unique_ptr<RifCsvUserDataFileParser>(new RifCsvUserDataFileParser(fileName, errorText));
|
||||||
@@ -100,14 +98,25 @@ bool RifCsvUserData::values(const RifEclipseSummaryAddress& resultAddress, std::
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
const std::vector<time_t>& RifCsvUserData::timeSteps(const RifEclipseSummaryAddress& resultAddress) const
|
const std::vector<time_t>& RifCsvUserData::timeSteps(const RifEclipseSummaryAddress& resultAddress) const
|
||||||
{
|
{
|
||||||
auto search = m_mapFromAddressToTimeStepIndex.find(resultAddress);
|
// First, check whether date time values exist for the current address
|
||||||
if (search != m_mapFromAddressToTimeStepIndex.end())
|
auto search = m_mapFromAddressToResultIndex.find(resultAddress);
|
||||||
|
if (search != m_mapFromAddressToResultIndex.end())
|
||||||
{
|
{
|
||||||
return m_timeSteps;
|
size_t index = m_mapFromAddressToResultIndex.at(resultAddress);
|
||||||
|
if (!m_parser->tableData().columnInfos()[index].dateTimeValues.empty())
|
||||||
|
{
|
||||||
|
return m_parser->tableData().columnInfos()[index].dateTimeValues;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then check for a separate date time column
|
||||||
|
int index = m_parser->tableData().dateTimeColumnIndex();
|
||||||
|
if (index >= 0)
|
||||||
|
{
|
||||||
|
return m_parser->tableData().columnInfos()[index].dateTimeValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<time_t> emptyVector;
|
static std::vector<time_t> emptyVector;
|
||||||
|
|
||||||
return emptyVector;
|
return emptyVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,19 +147,6 @@ void RifCsvUserData::buildTimeStepsAndMappings()
|
|||||||
{
|
{
|
||||||
auto tableData = m_parser->tableData();
|
auto tableData = m_parser->tableData();
|
||||||
|
|
||||||
std::vector<time_t> timeStepsForTable = createTimeSteps(tableData);
|
|
||||||
|
|
||||||
if (timeStepsForTable.empty())
|
|
||||||
{
|
|
||||||
RiaLogging::warning(QString("Failed to find time data for table in file"));
|
|
||||||
RiaLogging::warning(QString("No data for this table is imported"));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_timeSteps = timeStepsForTable;
|
|
||||||
|
|
||||||
|
|
||||||
for (size_t columnIndex = 0; columnIndex < tableData.columnInfos().size(); columnIndex++)
|
for (size_t columnIndex = 0; columnIndex < tableData.columnInfos().size(); columnIndex++)
|
||||||
{
|
{
|
||||||
const Column& ci = tableData.columnInfos()[columnIndex];
|
const Column& ci = tableData.columnInfos()[columnIndex];
|
||||||
@@ -161,26 +157,7 @@ void RifCsvUserData::buildTimeStepsAndMappings()
|
|||||||
m_allResultAddresses.insert(sumAddress);
|
m_allResultAddresses.insert(sumAddress);
|
||||||
if (sumAddress.isErrorResult()) m_allErrorAddresses.insert(sumAddress);
|
if (sumAddress.isErrorResult()) m_allErrorAddresses.insert(sumAddress);
|
||||||
|
|
||||||
m_mapFromAddressToTimeStepIndex[sumAddress] = m_timeSteps.size() - 1;
|
|
||||||
m_mapFromAddressToResultIndex[sumAddress] = columnIndex;
|
m_mapFromAddressToResultIndex[sumAddress] = columnIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
///
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
std::vector<time_t> RifCsvUserData::createTimeSteps(const TableData& tableData)
|
|
||||||
{
|
|
||||||
std::vector<time_t> tsVector;
|
|
||||||
|
|
||||||
const Column& col = tableData.columnInfos()[0];
|
|
||||||
|
|
||||||
tsVector.reserve(col.dateTimeValues.size());
|
|
||||||
for (const QDateTime& qdt : col.dateTimeValues)
|
|
||||||
{
|
|
||||||
tsVector.push_back(qdt.toTime_t());
|
|
||||||
}
|
|
||||||
|
|
||||||
return tsVector;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -54,12 +54,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void buildTimeStepsAndMappings();
|
void buildTimeStepsAndMappings();
|
||||||
static std::vector<time_t> createTimeSteps(const TableData& table);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<RifCsvUserDataParser> m_parser;
|
std::unique_ptr<RifCsvUserDataParser> m_parser;
|
||||||
std::vector<time_t> m_timeSteps;
|
|
||||||
|
|
||||||
std::map<RifEclipseSummaryAddress, size_t > m_mapFromAddressToTimeStepIndex;
|
|
||||||
std::map<RifEclipseSummaryAddress, size_t > m_mapFromAddressToResultIndex;
|
std::map<RifEclipseSummaryAddress, size_t > m_mapFromAddressToResultIndex;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,6 +37,26 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Internal constants
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
#define DOUBLE_INF std::numeric_limits<double>::infinity()
|
||||||
|
|
||||||
|
#define ISO_DATE_FORMAT "yyyy-MM-dd"
|
||||||
|
#define TIME_FORMAT "hh:mm:ss"
|
||||||
|
|
||||||
|
using Sample = std::pair<time_t, double>;
|
||||||
|
using SampleList = std::vector<Sample>;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
enum CsvLineBasedColumnType { DATE, VECTOR, VALUE, ERROR_VALUE, COMMENTS };
|
||||||
|
const std::vector<QString> CSV_LINE_BASED_COL_NAMES = { "DATE", "VECTOR", "VALUE", "ERROR", "COMMENTS" };
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
@@ -59,7 +79,8 @@ RifCsvUserDataParser::~RifCsvUserDataParser()
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
bool RifCsvUserDataParser::parse(const AsciiDataParseOptions& parseOptions)
|
bool RifCsvUserDataParser::parse(const AsciiDataParseOptions& parseOptions)
|
||||||
{
|
{
|
||||||
return parseData(parseOptions);
|
if (determineCsvLayout() == LineBased) return parseLineBasedData();
|
||||||
|
return parseColumnBasedData(parseOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@@ -96,6 +117,29 @@ const Column* RifCsvUserDataParser::dateTimeColumn() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
std::vector<int> RifCsvUserDataParser::parseLineBasedHeader(QStringList headerCols)
|
||||||
|
{
|
||||||
|
std::vector<int> colIndexes;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)CSV_LINE_BASED_COL_NAMES.size(); i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < (int)headerCols.size(); j++)
|
||||||
|
{
|
||||||
|
if (headerCols[j] == CSV_LINE_BASED_COL_NAMES[i])
|
||||||
|
{
|
||||||
|
colIndexes.push_back(j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 3 && (int)colIndexes.size() < i + 1) return {};
|
||||||
|
}
|
||||||
|
return colIndexes;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@@ -174,6 +218,31 @@ QString RifCsvUserDataParser::previewText(int lineCount, const AsciiDataParseOpt
|
|||||||
return preview;
|
return preview;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
RifCsvUserDataParser::CsvLayout RifCsvUserDataParser::determineCsvLayout()
|
||||||
|
{
|
||||||
|
QTextStream* dataStream = openDataStream();
|
||||||
|
QString firstLine;
|
||||||
|
|
||||||
|
QStringList headers;
|
||||||
|
while (!dataStream->atEnd())
|
||||||
|
{
|
||||||
|
firstLine = dataStream->readLine();
|
||||||
|
if (firstLine.isEmpty()) continue;
|
||||||
|
headers = firstLine.split(';');
|
||||||
|
if (headers.size() < 3 || headers.size() > 5) continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
closeDataStream();
|
||||||
|
|
||||||
|
if (headers.contains(CSV_LINE_BASED_COL_NAMES[DATE])
|
||||||
|
&& headers.contains(CSV_LINE_BASED_COL_NAMES[VECTOR])
|
||||||
|
&& headers.contains(CSV_LINE_BASED_COL_NAMES[VALUE])) return LineBased;
|
||||||
|
return ColumnBased;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@@ -210,7 +279,7 @@ bool RifCsvUserDataParser::parseColumnInfo(QTextStream* dataStream, const AsciiD
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
bool RifCsvUserDataParser::parseData(const AsciiDataParseOptions& parseOptions)
|
bool RifCsvUserDataParser::parseColumnBasedData(const AsciiDataParseOptions& parseOptions)
|
||||||
{
|
{
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
enum { FIRST_DATA_ROW, DATA_ROW } parseState = FIRST_DATA_ROW;
|
enum { FIRST_DATA_ROW, DATA_ROW } parseState = FIRST_DATA_ROW;
|
||||||
@@ -326,7 +395,8 @@ bool RifCsvUserDataParser::parseData(const AsciiDataParseOptions& parseOptions)
|
|||||||
if (m_errorText) m_errorText->append("CSV import: Failed to parse date time value");
|
if (m_errorText) m_errorText->append("CSV import: Failed to parse date time value");
|
||||||
throw 0;
|
throw 0;
|
||||||
}
|
}
|
||||||
col.dateTimeValues.push_back(dt);
|
col.dateTimeValues.push_back(dt.toTime_t());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
@@ -348,6 +418,148 @@ bool RifCsvUserDataParser::parseData(const AsciiDataParseOptions& parseOptions)
|
|||||||
return !errors;
|
return !errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
bool RifCsvUserDataParser::parseLineBasedData()
|
||||||
|
{
|
||||||
|
bool errors = false;
|
||||||
|
QTextStream* dataStream = openDataStream();
|
||||||
|
std::vector<CsvLineBasedColumnType> columns;
|
||||||
|
std::map<RifEclipseSummaryAddress, std::vector<std::pair<time_t, double>>> addressesAndData;
|
||||||
|
std::vector<int> colIndexes;
|
||||||
|
|
||||||
|
// Parse header
|
||||||
|
int lineCount = 0;
|
||||||
|
bool headerFound = false;
|
||||||
|
bool expectErrorValue = false;
|
||||||
|
|
||||||
|
while (!dataStream->atEnd() && !errors)
|
||||||
|
{
|
||||||
|
lineCount++;
|
||||||
|
|
||||||
|
QString line = dataStream->readLine();
|
||||||
|
if (line.trimmed().isEmpty()) continue;
|
||||||
|
|
||||||
|
QStringList dataItems = RifFileParseTools::splitLineAndTrim(line, ";");
|
||||||
|
if (dataItems.size() < 3 || dataItems.size() > 5) continue;
|
||||||
|
|
||||||
|
if (!headerFound)
|
||||||
|
{
|
||||||
|
colIndexes = parseLineBasedHeader(dataItems);
|
||||||
|
if (!colIndexes.empty())
|
||||||
|
{
|
||||||
|
headerFound = true;
|
||||||
|
expectErrorValue = colIndexes.size() > ERROR_VALUE && colIndexes[ERROR_VALUE] >= 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dataItems.size() != (int)colIndexes.size()) continue;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto textAddr = dataItems[colIndexes[VECTOR]];
|
||||||
|
auto addr = RifEclipseSummaryAddress::fromEclipseTextAddress(textAddr.toStdString());
|
||||||
|
auto errAddr = addr;
|
||||||
|
errAddr.setAsErrorResult();
|
||||||
|
|
||||||
|
if (!addr.isValid()) continue;
|
||||||
|
|
||||||
|
// VECTOR
|
||||||
|
{
|
||||||
|
if (addressesAndData.find(addr) == addressesAndData.end())
|
||||||
|
{
|
||||||
|
addressesAndData.insert(std::make_pair(addr, std::vector<Sample>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create error address if error value is expected
|
||||||
|
if (expectErrorValue)
|
||||||
|
{
|
||||||
|
if (addressesAndData.find(errAddr) == addressesAndData.end())
|
||||||
|
{
|
||||||
|
addressesAndData.insert(std::make_pair(errAddr, std::vector<Sample>()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DATE
|
||||||
|
QDateTime dateTime;
|
||||||
|
{
|
||||||
|
auto dateText = dataItems[colIndexes[DATE]].toStdString();
|
||||||
|
|
||||||
|
dateTime = tryParseDateTime(dateText, ISO_DATE_FORMAT);
|
||||||
|
if (!dateTime.isValid())
|
||||||
|
{
|
||||||
|
// Try to match date and time
|
||||||
|
dateTime = tryParseDateTime(dateText, QString(ISO_DATE_FORMAT) + " " + TIME_FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dateTime.isValid())
|
||||||
|
{
|
||||||
|
if (m_errorText) m_errorText->append(QString("CSV import: Failed to parse date time value in line %1").arg(QString::number(lineCount)));
|
||||||
|
throw 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VALUE
|
||||||
|
{
|
||||||
|
bool parseOk = true;
|
||||||
|
double value = QLocale::c().toDouble(dataItems[colIndexes[VALUE]], &parseOk);
|
||||||
|
|
||||||
|
if (!parseOk)
|
||||||
|
{
|
||||||
|
if (m_errorText) m_errorText->append(QString("CSV import: Failed to parse numeric value in line %1\n").arg(QString::number(lineCount)));
|
||||||
|
throw 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& samples = addressesAndData[addr];
|
||||||
|
samples.push_back(std::make_pair(dateTime.toTime_t(), value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ERROR VALUE
|
||||||
|
if(expectErrorValue)
|
||||||
|
{
|
||||||
|
bool parseOk = true;
|
||||||
|
double value = QLocale::c().toDouble(dataItems[colIndexes[ERROR_VALUE]], &parseOk);
|
||||||
|
|
||||||
|
if (!parseOk) value = DOUBLE_INF;
|
||||||
|
|
||||||
|
auto& samples = addressesAndData[errAddr];
|
||||||
|
samples.push_back(std::make_pair(dateTime.toTime_t(), value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closeDataStream();
|
||||||
|
|
||||||
|
if (!errors)
|
||||||
|
{
|
||||||
|
std::vector<Column> columnInfoList;
|
||||||
|
for (const auto& item : addressesAndData)
|
||||||
|
{
|
||||||
|
auto samples = item.second;
|
||||||
|
|
||||||
|
// Sort samples by time
|
||||||
|
std::sort(samples.begin(), samples.end(),
|
||||||
|
[](const Sample& s1, const Sample& s2) {return s1.first < s2.first; });
|
||||||
|
|
||||||
|
// Copy
|
||||||
|
Column c = Column::createColumnInfoFromCsvData(item.first, "");
|
||||||
|
c.dataType = Column::NUMERIC;
|
||||||
|
|
||||||
|
for (const auto& sample : samples)
|
||||||
|
{
|
||||||
|
c.dateTimeValues.push_back(sample.first);
|
||||||
|
c.values.push_back(sample.second);
|
||||||
|
}
|
||||||
|
columnInfoList.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
TableData td("", "", columnInfoList);
|
||||||
|
m_tableData = td;
|
||||||
|
}
|
||||||
|
return !errors;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ class AsciiDataParseOptions;
|
|||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
class RifCsvUserDataParser
|
class RifCsvUserDataParser
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
enum CsvLayout { ColumnBased, LineBased };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RifCsvUserDataParser(QString* errorText = nullptr);
|
RifCsvUserDataParser(QString* errorText = nullptr);
|
||||||
virtual ~RifCsvUserDataParser();
|
virtual ~RifCsvUserDataParser();
|
||||||
@@ -52,6 +55,8 @@ public:
|
|||||||
bool parseColumnInfo(const AsciiDataParseOptions& parseOptions);
|
bool parseColumnInfo(const AsciiDataParseOptions& parseOptions);
|
||||||
QString previewText(int lineCount, const AsciiDataParseOptions& parseOptions);
|
QString previewText(int lineCount, const AsciiDataParseOptions& parseOptions);
|
||||||
|
|
||||||
|
CsvLayout determineCsvLayout();
|
||||||
|
|
||||||
QString tryDetermineCellSeparator();
|
QString tryDetermineCellSeparator();
|
||||||
QString tryDetermineDecimalSeparator(const QString& cellSeparator);
|
QString tryDetermineDecimalSeparator(const QString& cellSeparator);
|
||||||
|
|
||||||
@@ -62,10 +67,13 @@ protected:
|
|||||||
virtual void closeDataStream() = 0;
|
virtual void closeDataStream() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::vector<int> parseLineBasedHeader(QStringList headerCols);
|
||||||
|
|
||||||
bool parseColumnInfo(QTextStream* dataStream,
|
bool parseColumnInfo(QTextStream* dataStream,
|
||||||
const AsciiDataParseOptions& parseOptions,
|
const AsciiDataParseOptions& parseOptions,
|
||||||
std::vector<Column>* columnInfoList);
|
std::vector<Column>* columnInfoList);
|
||||||
bool parseData(const AsciiDataParseOptions& parseOptions);
|
bool parseColumnBasedData(const AsciiDataParseOptions& parseOptions);
|
||||||
|
bool parseLineBasedData();
|
||||||
static QDateTime tryParseDateTime(const std::string& colData, const QString& format);
|
static QDateTime tryParseDateTime(const std::string& colData, const QString& format);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -942,9 +942,9 @@ size_t Column::itemCount() const
|
|||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
Column Column::createColumnInfoFromRsmData(const std::string& quantity, const std::string& unit, const RifEclipseSummaryAddress& adr)
|
Column Column::createColumnInfoFromRsmData(const std::string& quantity, const std::string& unit, const RifEclipseSummaryAddress& addr)
|
||||||
{
|
{
|
||||||
Column ci(adr, unit);
|
Column ci(addr, unit);
|
||||||
|
|
||||||
if (RifEclipseUserDataKeywordTools::isDate(quantity))
|
if (RifEclipseUserDataKeywordTools::isDate(quantity))
|
||||||
{
|
{
|
||||||
@@ -970,6 +970,24 @@ Column Column::createColumnInfoFromCsvData(const RifEclipseSummaryAddress& addr,
|
|||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
std::vector<QDateTime> Column::qDateTimeValues() const
|
||||||
|
{
|
||||||
|
std::vector<QDateTime> output;
|
||||||
|
for (auto t : dateTimeValues) output.push_back(RiaQDateTimeTools::fromTime_t(t));
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
int TableData::dateTimeColumnIndex() const
|
||||||
|
{
|
||||||
|
return m_dateTimeColumnIndex;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
size_t itemCount() const;
|
size_t itemCount() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Column createColumnInfoFromRsmData(const std::string& quantity, const std::string& unit, const RifEclipseSummaryAddress& adr);
|
static Column createColumnInfoFromRsmData(const std::string& quantity, const std::string& unit, const RifEclipseSummaryAddress& addr);
|
||||||
static Column createColumnInfoFromCsvData(const RifEclipseSummaryAddress& addr, const std::string& unit);
|
static Column createColumnInfoFromCsvData(const RifEclipseSummaryAddress& addr, const std::string& unit);
|
||||||
|
|
||||||
RifEclipseSummaryAddress summaryAddress;
|
RifEclipseSummaryAddress summaryAddress;
|
||||||
@@ -71,7 +71,10 @@ public:
|
|||||||
// Data containers
|
// Data containers
|
||||||
std::vector<double> values;
|
std::vector<double> values;
|
||||||
std::vector<std::string > textValues;
|
std::vector<std::string > textValues;
|
||||||
std::vector<QDateTime> dateTimeValues;
|
//std::vector<QDateTime> dateTimeValues;
|
||||||
|
std::vector<time_t> dateTimeValues;
|
||||||
|
|
||||||
|
std::vector<QDateTime> qDateTimeValues() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -89,8 +92,17 @@ public:
|
|||||||
const std::vector<Column>& columnInfos)
|
const std::vector<Column>& columnInfos)
|
||||||
: m_origin(origin),
|
: m_origin(origin),
|
||||||
m_startDate(startDate),
|
m_startDate(startDate),
|
||||||
|
m_dateTimeColumnIndex(-1),
|
||||||
m_columnInfos(columnInfos)
|
m_columnInfos(columnInfos)
|
||||||
{
|
{
|
||||||
|
for (size_t i = 0; i < columnInfos.size(); i++)
|
||||||
|
{
|
||||||
|
if (columnInfos[i].dataType == Column::DATETIME)
|
||||||
|
{
|
||||||
|
m_dateTimeColumnIndex = (int)i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string origin() const
|
std::string origin() const
|
||||||
@@ -113,11 +125,13 @@ public:
|
|||||||
return m_columnInfos;
|
return m_columnInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dateTimeColumnIndex() const;
|
||||||
QDateTime findFirstDate() const;
|
QDateTime findFirstDate() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_origin;
|
std::string m_origin;
|
||||||
std::string m_startDate;
|
std::string m_startDate;
|
||||||
|
int m_dateTimeColumnIndex;
|
||||||
|
|
||||||
std::vector<Column> m_columnInfos;
|
std::vector<Column> m_columnInfos;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -70,10 +70,9 @@ bool RifReaderObservedData::open(const QString& headerFileName,
|
|||||||
{
|
{
|
||||||
if (m_asciiParser && m_asciiParser->dateTimeColumn())
|
if (m_asciiParser && m_asciiParser->dateTimeColumn())
|
||||||
{
|
{
|
||||||
for (QDateTime timeStep : m_asciiParser->dateTimeColumn()->dateTimeValues)
|
for (time_t timeStep : m_asciiParser->dateTimeColumn()->dateTimeValues)
|
||||||
{
|
{
|
||||||
time_t t = timeStep.toTime_t();
|
m_timeSteps.push_back(timeStep);
|
||||||
m_timeSteps.push_back(t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_allResultAddresses.clear();
|
m_allResultAddresses.clear();
|
||||||
|
|||||||
@@ -169,11 +169,14 @@ RimObservedData* RimObservedDataCollection::createAndAddCvsObservedDataFromFile(
|
|||||||
}
|
}
|
||||||
parseOptions->setUiModeImport(fileName);
|
parseOptions->setUiModeImport(fileName);
|
||||||
|
|
||||||
|
if (parseOptions->uiModeImport() != RicPasteAsciiDataToSummaryPlotFeatureUi::UI_MODE_SILENT)
|
||||||
|
{
|
||||||
caf::PdmUiPropertyViewDialog propertyDialog(nullptr, parseOptions, "CSV Import Options", "");
|
caf::PdmUiPropertyViewDialog propertyDialog(nullptr, parseOptions, "CSV Import Options", "");
|
||||||
if (propertyDialog.exec() != QDialog::Accepted)
|
if (propertyDialog.exec() != QDialog::Accepted)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
caf::PdmSettings::writeFieldsToApplicationStore(parseOptions);
|
caf::PdmSettings::writeFieldsToApplicationStore(parseOptions);
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ TEST(RifColumnBasedAsciiParserTest, TestDateFormatYyyymmddWithDash)
|
|||||||
ASSERT_TRUE(parser.parse(parseOptions));
|
ASSERT_TRUE(parser.parse(parseOptions));
|
||||||
ASSERT_TRUE(parser.dateTimeColumn() != nullptr);
|
ASSERT_TRUE(parser.dateTimeColumn() != nullptr);
|
||||||
|
|
||||||
std::vector<QDateTime> timeSteps = parser.dateTimeColumn()->dateTimeValues;
|
std::vector<QDateTime> timeSteps = parser.dateTimeColumn()->qDateTimeValues();
|
||||||
|
|
||||||
ASSERT_EQ(size_t(4), timeSteps.size());
|
ASSERT_EQ(size_t(4), timeSteps.size());
|
||||||
EXPECT_EQ("1993-02-23", timeSteps[0].toString(parseOptions.dateFormat).toStdString());
|
EXPECT_EQ("1993-02-23", timeSteps[0].toString(parseOptions.dateFormat).toStdString());
|
||||||
@@ -69,7 +69,7 @@ TEST(RifColumnBasedAsciiParserTest, TestDateFormatYymmddWithDot)
|
|||||||
ASSERT_TRUE(parser.parse(parseOptions));
|
ASSERT_TRUE(parser.parse(parseOptions));
|
||||||
ASSERT_TRUE(parser.dateTimeColumn() != nullptr);
|
ASSERT_TRUE(parser.dateTimeColumn() != nullptr);
|
||||||
|
|
||||||
std::vector<QDateTime> timeSteps = parser.dateTimeColumn()->dateTimeValues;
|
std::vector<QDateTime> timeSteps = parser.dateTimeColumn()->qDateTimeValues();
|
||||||
|
|
||||||
ASSERT_EQ(size_t(4), timeSteps.size());
|
ASSERT_EQ(size_t(4), timeSteps.size());
|
||||||
EXPECT_EQ("93.02.23", timeSteps[0].toString(parseOptions.dateFormat).toStdString());
|
EXPECT_EQ("93.02.23", timeSteps[0].toString(parseOptions.dateFormat).toStdString());
|
||||||
@@ -98,7 +98,7 @@ TEST(RifColumnBasedAsciiParserTest, TestDateFormatDdmmyyWithDot)
|
|||||||
ASSERT_TRUE(parser.parse(parseOptions));
|
ASSERT_TRUE(parser.parse(parseOptions));
|
||||||
ASSERT_TRUE(parser.dateTimeColumn() != nullptr);
|
ASSERT_TRUE(parser.dateTimeColumn() != nullptr);
|
||||||
|
|
||||||
std::vector<QDateTime> timeSteps = parser.dateTimeColumn()->dateTimeValues;
|
std::vector<QDateTime> timeSteps = parser.dateTimeColumn()->qDateTimeValues();
|
||||||
|
|
||||||
ASSERT_EQ(size_t(4), timeSteps.size());
|
ASSERT_EQ(size_t(4), timeSteps.size());
|
||||||
EXPECT_EQ("23.02.93", timeSteps[0].toString(parseOptions.dateFormat).toStdString());
|
EXPECT_EQ("23.02.93", timeSteps[0].toString(parseOptions.dateFormat).toStdString());
|
||||||
|
|||||||
Reference in New Issue
Block a user