#3060 Resampled plot export. Implement dialog. Resample plot data according to spec from Equinor

This commit is contained in:
Bjørn Erik Jensen 2018-06-20 09:41:01 +02:00
parent 7e6943aa96
commit 2eef989389
8 changed files with 308 additions and 23 deletions

View File

@ -296,3 +296,21 @@ QDateTime RiaQDateTimeTools::truncateTime(const QDateTime& dt, DateTimePeriod pe
CVF_ASSERT(false);
return createUtcDateTime();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<DateTimePeriodInfo> RiaQDateTimeTools::dateTimePeriodInfoList()
{
return std::vector<DateTimePeriodInfo>(
{
{ DateTimePeriod::NONE, "None" },
{ DateTimePeriod::DECADE, "Decade" },
{ DateTimePeriod::YEAR, "Year" },
{ DateTimePeriod::HALFYEAR, "Half Year" },
{ DateTimePeriod::QUARTER, "Quarter" },
{ DateTimePeriod::MONTH, "Month" },
{ DateTimePeriod::WEEK, "Week" },
{ DateTimePeriod::DAY, "Day" },
});
}

View File

@ -21,12 +21,16 @@
#include <qglobal.h>
#include <qnamespace.h>
#include <QString>
#include <string>
#include <vector>
class QDateTime;
class QDate;
class QTime;
class DateTimeSpan;
class DateTimePeriodInfo;
//==================================================================================================
//
@ -85,6 +89,8 @@ public:
static const DateTimeSpan timeSpan(DateTimePeriod period);
static QDateTime truncateTime(const QDateTime& dt, DateTimePeriod period);
static std::vector<DateTimePeriodInfo> dateTimePeriodInfoList();
private:
static quint64 secondsInDay();
static quint64 secondsInYear();
@ -110,3 +116,13 @@ private:
int m_months;
int m_days;
};
//==================================================================================================
///
//==================================================================================================
class DateTimePeriodInfo
{
public:
DateTimePeriod period;
QString name;
};

View File

@ -70,6 +70,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicSummaryCaseRestartDialog.h
${CMAKE_CURRENT_LIST_DIR}/RicImportEnsembleFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryGroupFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicConvertGroupToEnsembleFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicResampleDialog.h
)
@ -138,6 +139,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicSummaryCaseRestartDialog.cpp
${CMAKE_CURRENT_LIST_DIR}/RicImportEnsembleFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryGroupFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicConvertGroupToEnsembleFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicResampleDialog.cpp
)
@ -153,6 +155,7 @@ list(APPEND QT_MOC_HEADERS
${CMAKE_CURRENT_LIST_DIR}/RicGridStatisticsDialog.h
${CMAKE_CURRENT_LIST_DIR}/RicFileHierarchyDialog.h
${CMAKE_CURRENT_LIST_DIR}/RicSummaryCaseRestartDialog.h
${CMAKE_CURRENT_LIST_DIR}/RicResampleDialog.h
)
source_group( "CommandFeature" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CMAKE_CURRENT_LIST_DIR}/CMakeLists_files.cmake )

View File

@ -0,0 +1,140 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017- Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicResampleDialog.h"
#include "RiaApplication.h"
#include "RiuTools.h"
#include <QVBoxLayout>
#include <QLabel>
#include <QComboBox>
#include <QLineEdit>
#include <QTextEdit>
#include <QDialogButtonBox>
#include <QPushButton>
#include <QToolBar>
#include <QAction>
#include <QFileDialog>
#include <QGroupBox>
#include <QListWidget>
#include <QAbstractItemView>
#include <QMenu>
#include <QTime>
#define DEFAULT_DIALOG_WIDTH 250
#define DEFAULT_DIALOG_HEIGHT 100
#define DEFAULT_DIALOG_TITLE "Export Plot Data"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicResampleDialog::RicResampleDialog(QWidget* parent)
: QDialog(parent, RiuTools::defaultDialogFlags())
{
// Create widgets
m_label = new QLabel();
m_timePeriodCombo = new QComboBox();
m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
// Connect to signals
connect(m_buttons, SIGNAL(accepted()), this, SLOT(slotDialogOkClicked()));
connect(m_buttons, SIGNAL(rejected()), this, SLOT(slotDialogCancelClicked()));
// Set widget properties
m_label->setText("Resampling Period");
// Define layout
QVBoxLayout* dialogLayout = new QVBoxLayout();
QHBoxLayout* periodLayout = new QHBoxLayout();
periodLayout->addWidget(m_label);
periodLayout->addWidget(m_timePeriodCombo);
dialogLayout->addLayout(periodLayout);
dialogLayout->addWidget(m_buttons);
setLayout(dialogLayout);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicResampleDialog::~RicResampleDialog()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicResampleDialogResult RicResampleDialog::openDialog(QWidget *parent /*= 0*/,
const QString &caption /*= QString()*/)
{
RicResampleDialog dialog(parent);
if(!caption.isEmpty()) dialog.setWindowTitle(caption);
else dialog.setWindowTitle(DEFAULT_DIALOG_TITLE);
dialog.setPeriodOptions(RiaQDateTimeTools::dateTimePeriodInfoList());
dialog.resize(DEFAULT_DIALOG_WIDTH, DEFAULT_DIALOG_HEIGHT);
dialog.exec();
return RicResampleDialogResult(dialog.result() == QDialog::Accepted, dialog.selectedDateTimePeriod());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicResampleDialog::setPeriodOptions(const std::vector<DateTimePeriodInfo>& dateTimePeriodInfos)
{
QStringList s;
for (auto& item : dateTimePeriodInfos)
{
QString text = item.period != DateTimePeriod::NONE ? item.name : "No Resampling";
m_timePeriodCombo->addItem(text, QVariant((int)item.period));
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
DateTimePeriod RicResampleDialog::selectedDateTimePeriod() const
{
int currIndex = m_timePeriodCombo->currentIndex();
return (DateTimePeriod)m_timePeriodCombo->itemData(currIndex).toInt();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicResampleDialog::slotDialogOkClicked()
{
accept();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicResampleDialog::slotDialogCancelClicked()
{
reject();
}

View File

@ -0,0 +1,79 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017- Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiaQDateTimeTools.h"
#include "cafPdmPointer.h"
#include <QDialog>
class QLabel;
class QComboBox;
class QLineEdit;
class QTextEdit;
class QDialogButtonBox;
class QPushButton;
class QMainWindow;
class QListWidget;
class RicResampleDialogResult;
class DateTimePeriodInfo;
//==================================================================================================
///
//==================================================================================================
class RicResampleDialog : public QDialog
{
Q_OBJECT
public:
RicResampleDialog(QWidget* parent);
~RicResampleDialog();
static RicResampleDialogResult openDialog(QWidget *parent = nullptr,
const QString& caption = QString());
private:
void setPeriodOptions(const std::vector<DateTimePeriodInfo>& dateTimePeriodInfos);
DateTimePeriod selectedDateTimePeriod() const;
private slots:
void slotDialogOkClicked();
void slotDialogCancelClicked();
private:
QLabel* m_label;
QComboBox* m_timePeriodCombo;
QDialogButtonBox* m_buttons;
};
//==================================================================================================
///
//==================================================================================================
class RicResampleDialogResult
{
public:
RicResampleDialogResult(bool ok, DateTimePeriod period) :
ok(ok), period(period) {}
bool ok;
DateTimePeriod period;
};

View File

@ -21,6 +21,8 @@
#include "RiaApplication.h"
#include "RiaLogging.h"
#include "RicResampleDialog.h"
#include "RimSummaryPlot.h"
#include "RiuMainWindow.h"
@ -67,8 +69,9 @@ void RicAsciiExportSummaryPlotFeature::onActionTriggered(bool isChecked)
caf::SelectionManager::instance()->objectsByType(&selectedSummaryPlots);
QString defaultDir = RiaApplication::instance()->lastUsedDialogDirectoryWithFallback("PLOT_ASCIIEXPORT_DIR", projectFolder);
caf::ProgressInfo pi(selectedSummaryPlots.size(), QString("Exporting plot data to ASCII"));
size_t progress = 0;
// Ask user about resampling
auto result = RicResampleDialog::openDialog();
if (!result.ok) return;
if (selectedSummaryPlots.size() == 1)
{
@ -76,7 +79,11 @@ void RicAsciiExportSummaryPlotFeature::onActionTriggered(bool isChecked)
QString defaultFileName = defaultDir + "/" + caf::Utils::makeValidFileBasename((summaryPlot->description())) + ".ascii";
QString fileName = QFileDialog::getSaveFileName(nullptr, "Select File for Summary Plot Export", defaultFileName, "Text File(*.ascii);;All files(*.*)");
if (fileName.isEmpty()) return;
RicAsciiExportSummaryPlotFeature::exportAsciiForSummaryPlot(fileName, summaryPlot);
caf::ProgressInfo pi(selectedSummaryPlots.size(), QString("Exporting plot data to ASCII"));
size_t progress = 0;
RicAsciiExportSummaryPlotFeature::exportAsciiForSummaryPlot(fileName, summaryPlot, result.period);
progress++;
pi.setProgress(progress);
@ -94,11 +101,14 @@ void RicAsciiExportSummaryPlotFeature::onActionTriggered(bool isChecked)
bool writeFiles = caf::Utils::getSaveDirectoryAndCheckOverwriteFiles(defaultDir, fileNames, &saveDir);
if (!writeFiles) return;
caf::ProgressInfo pi(selectedSummaryPlots.size(), QString("Exporting plot data to ASCII"));
size_t progress = 0;
RiaLogging::info(QString("Writing to directory %1").arg(saveDir));
for (RimSummaryPlot* summaryPlot : selectedSummaryPlots)
{
QString fileName = saveDir + "/" + caf::Utils::makeValidFileBasename(summaryPlot->description()) + ".ascii";
RicAsciiExportSummaryPlotFeature::exportAsciiForSummaryPlot(fileName, summaryPlot);
RicAsciiExportSummaryPlotFeature::exportAsciiForSummaryPlot(fileName, summaryPlot, result.period);
progress++;
pi.setProgress(progress);
}
@ -117,7 +127,9 @@ void RicAsciiExportSummaryPlotFeature::setupActionLook(QAction* actionToSetup)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicAsciiExportSummaryPlotFeature::exportAsciiForSummaryPlot(const QString& fileName, const RimSummaryPlot* summaryPlot)
bool RicAsciiExportSummaryPlotFeature::exportAsciiForSummaryPlot(const QString& fileName,
const RimSummaryPlot* summaryPlot,
DateTimePeriod resamplingPeriod)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
@ -130,7 +142,7 @@ bool RicAsciiExportSummaryPlotFeature::exportAsciiForSummaryPlot(const QString&
QTextStream out(&file);
out << summaryPlot->description();
out << summaryPlot->asciiDataForPlotExport();
out << summaryPlot->asciiDataForPlotExport(resamplingPeriod);
out << "\n\n";
RiaLogging::info(QString("Competed writing values for summary plot(s) to file %1").arg(fileName));

View File

@ -18,6 +18,8 @@
#pragma once
#include "RiaQDateTimeTools.h"
#include "cafCmdFeature.h"
class RimSummaryPlot;
@ -35,5 +37,7 @@ protected:
virtual void setupActionLook(QAction* actionToSetup) override;
private:
static bool exportAsciiForSummaryPlot(const QString& fileName, const RimSummaryPlot* selectedSummaryPlots);
static bool exportAsciiForSummaryPlot(const QString& fileName,
const RimSummaryPlot* selectedSummaryPlots,
DateTimePeriod resamplingPeriod);
};

View File

@ -63,8 +63,15 @@
CAF_PDM_SOURCE_INIT(RimSummaryPlot, "SummaryPlot");
//--------------------------------------------------------------------------------------------------
/// Internal data
/// Internal types
//--------------------------------------------------------------------------------------------------
enum class ResampleAlgorithm
{
NONE,
DATA_DECIDES,
PERIOD_END
};
struct CurveData
{
QString name;
@ -75,9 +82,9 @@ struct CurveData
//--------------------------------------------------------------------------------------------------
/// Internal functions
//--------------------------------------------------------------------------------------------------
void prepareCaseCurvesForExport(DateTimePeriod period,
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
const std::vector<time_t> &timeSteps, const std::vector<CurveData>& curveData,
std::vector<time_t>* resampledTimeSteps, std::vector<CurveData>* resampledValues);
std::vector<time_t>* exportTimeSteps, std::vector<CurveData>* exportValues);
void appendToExportData(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData);
@ -315,7 +322,7 @@ QString RimSummaryPlot::asciiDataForPlotExport(DateTimePeriod resamplingPeriod)
out += "Case: " + caseNames[i];
out += "\n";
prepareCaseCurvesForExport(resamplingPeriod, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
prepareCaseCurvesForExport(resamplingPeriod, ResampleAlgorithm::DATA_DECIDES, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
appendToExportData(out, expTimeSteps, expCurveData);
}
}
@ -362,7 +369,7 @@ QString RimSummaryPlot::asciiDataForPlotExport(DateTimePeriod resamplingPeriod)
out += "Case: " + caseNames[i];
out += "\n";
prepareCaseCurvesForExport(resamplingPeriod, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
prepareCaseCurvesForExport(resamplingPeriod, ResampleAlgorithm::PERIOD_END, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
appendToExportData(out, expTimeSteps, expCurveData);
}
}
@ -400,7 +407,7 @@ QString RimSummaryPlot::asciiDataForPlotExport(DateTimePeriod resamplingPeriod)
out += "\n\n";
prepareCaseCurvesForExport(resamplingPeriod, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
prepareCaseCurvesForExport(DateTimePeriod::NONE, ResampleAlgorithm::NONE, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
appendToExportData(out, expTimeSteps, expCurveData);
}
}
@ -1640,14 +1647,14 @@ void RimSummaryPlot::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void prepareCaseCurvesForExport(DateTimePeriod period,
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
const std::vector<time_t> &timeSteps, const std::vector<CurveData>& curveData,
std::vector<time_t>* resampledTimeSteps, std::vector<CurveData>* resampledCurveData)
std::vector<time_t>* exportTimeSteps, std::vector<CurveData>* exportCurveData)
{
RiaTimeHistoryCurveResampler resampler;
resampledTimeSteps->clear();
resampledCurveData->clear();
exportTimeSteps->clear();
exportCurveData->clear();
if (period != DateTimePeriod::NONE)
{
@ -1655,20 +1662,26 @@ void prepareCaseCurvesForExport(DateTimePeriod period,
{
resampler.setCurveData(curveDataItem.values, timeSteps);
if (curveDataItem.address.hasAccumulatedData()) resampler.resampleAndComputePeriodEndValues(period);
else resampler.resampleAndComputeWeightedMeanValues(period);
if (curveDataItem.address.hasAccumulatedData() || algorithm == ResampleAlgorithm::PERIOD_END)
{
resampler.resampleAndComputePeriodEndValues(period);
}
else
{
resampler.resampleAndComputeWeightedMeanValues(period);
}
auto cd = curveDataItem;
cd.values = resampler.resampledValues();
resampledCurveData->push_back(cd);
exportCurveData->push_back(cd);
}
*resampledTimeSteps = resampler.resampledTimeSteps();
*exportTimeSteps = resampler.resampledTimeSteps();
}
else
{
*resampledTimeSteps = timeSteps;
*resampledCurveData = curveData;
*exportTimeSteps = timeSteps;
*exportCurveData = curveData;
}
}