#3086 Resampled plot export. When data are resampled, write all data into the same table in export file

This commit is contained in:
Bjørn Erik Jensen 2018-06-27 10:31:07 +02:00
parent 9ea8622953
commit 28d093f54a
3 changed files with 201 additions and 78 deletions

View File

@ -85,6 +85,27 @@ const std::vector<double>& RiaTimeHistoryCurveResampler::resampledValues() const
return m_values; return m_values;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<time_t> RiaTimeHistoryCurveResampler::timeStepsFromTimeRange(DateTimePeriod period, time_t minTime, time_t maxTime)
{
CVF_ASSERT(minTime <= maxTime);
auto firstOriginalTimeStep = QDT::fromTime_t(minTime);
auto lastOriginalTimeStep = QDT::fromTime_t(maxTime);
auto currTimeStep = firstResampledTimeStep(firstOriginalTimeStep, period);
std::vector<time_t> timeSteps;
while (QDT::lessThanOrEqualTo(currTimeStep, lastOriginalTimeStep))
{
timeSteps.push_back(currTimeStep.toTime_t());
currTimeStep = QDT::addPeriod(currTimeStep, period);
}
return timeSteps;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -42,13 +42,15 @@ public:
const std::vector<time_t>& resampledTimeSteps() const; const std::vector<time_t>& resampledTimeSteps() const;
const std::vector<double>& resampledValues() const; const std::vector<double>& resampledValues() const;
static std::vector<time_t> timeStepsFromTimeRange(DateTimePeriod period, time_t minTime, time_t maxTime);
private: private:
void computeWeightedMeanValues(DateTimePeriod period); void computeWeightedMeanValues(DateTimePeriod period);
void computePeriodEndValues(DateTimePeriod period); void computePeriodEndValues(DateTimePeriod period);
void clearData(); void clearData();
void computeResampledTimeSteps(DateTimePeriod period); void computeResampledTimeSteps(DateTimePeriod period);
QDateTime firstResampledTimeStep(const QDateTime& firstTimestep, DateTimePeriod period); static QDateTime firstResampledTimeStep(const QDateTime& firstTimestep, DateTimePeriod period);
inline double interpolatedValue(time_t t, time_t t1, double v1, time_t t2, double v2); inline double interpolatedValue(time_t t, time_t t1, double v1, time_t t2, double v2);
private: private:

View File

@ -58,10 +58,16 @@
#include <QRectF> #include <QRectF>
#include <set> #include <set>
#include <limits>
CAF_PDM_SOURCE_INIT(RimSummaryPlot, "SummaryPlot"); CAF_PDM_SOURCE_INIT(RimSummaryPlot, "SummaryPlot");
//--------------------------------------------------------------------------------------------------
/// Internal constants
//--------------------------------------------------------------------------------------------------
#define DOUBLE_INF std::numeric_limits<double>::infinity()
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// Internal types /// Internal types
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -79,8 +85,19 @@ struct CurveData
std::vector<double> values; std::vector<double> values;
}; };
struct CurvesData class CurvesData
{ {
public:
CurvesData() : resamplePeriod(DateTimePeriod::NONE) {}
void clear()
{
resamplePeriod = DateTimePeriod::NONE;
caseNames.clear();
timeSteps.clear();
allCurveData.clear();
}
DateTimePeriod resamplePeriod;
std::vector<QString> caseNames; std::vector<QString> caseNames;
std::vector<std::vector<time_t> > timeSteps; std::vector<std::vector<time_t> > timeSteps;
std::vector<std::vector<CurveData>> allCurveData; std::vector<std::vector<CurveData>> allCurveData;
@ -95,10 +112,12 @@ void populateTimeHistoryCurvesData(std::vector<RimGridTimeHistoryCurve*> curves,
void populateAsciiDataCurvesData(std::vector<RimAsciiDataCurve*> curves, CurvesData* curvesData); void populateAsciiDataCurvesData(std::vector<RimAsciiDataCurve*> curves, CurvesData* curvesData);
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm, void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
const std::vector<time_t> &timeSteps, const std::vector<CurveData>& curveData, const CurvesData& inputCurvesData,
std::vector<time_t>* exportTimeSteps, std::vector<CurveData>* exportValues); CurvesData* resultCurvesData);
void appendToExportData(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData); void appendToExportDataForCase(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData);
void appendToExportData(QString& out, const std::vector<CurvesData>& curvesData);
CurvesData concatCurvesData(const std::vector<CurvesData>& curvesData);
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
@ -287,9 +306,7 @@ QString RimSummaryPlot::asciiDataForPlotExport(DateTimePeriod resamplingPeriod)
QString out; QString out;
RiaTimeHistoryCurveResampler resampler; RiaTimeHistoryCurveResampler resampler;
out += description(); // Summary and time history (from grid) curves
// Summary curves
{ {
std::vector<RimSummaryCurve*> curves; std::vector<RimSummaryCurve*> curves;
this->descendantsIncludingThisOfType(curves); this->descendantsIncludingThisOfType(curves);
@ -297,49 +314,24 @@ QString RimSummaryPlot::asciiDataForPlotExport(DateTimePeriod resamplingPeriod)
CurvesData summaryCurvesData; CurvesData summaryCurvesData;
populateSummaryCurvesData(curves, &summaryCurvesData); populateSummaryCurvesData(curves, &summaryCurvesData);
for (size_t i = 0; i < summaryCurvesData.timeSteps.size(); i++) //cases
{
// Data for export
std::vector<time_t> expTimeSteps;
std::vector<CurveData> expCurveData;
out += "\n\n";
out += "Case: " + summaryCurvesData.caseNames[i];
out += "\n";
prepareCaseCurvesForExport(resamplingPeriod,
ResampleAlgorithm::DATA_DECIDES,
summaryCurvesData.timeSteps[i],
summaryCurvesData.allCurveData[i],
&expTimeSteps,
&expCurveData);
appendToExportData(out, expTimeSteps, expCurveData);
}
}
// Time history curves (from grid)
{
CurvesData timeHistoryCurvesData; CurvesData timeHistoryCurvesData;
populateTimeHistoryCurvesData(m_gridTimeHistoryCurves.childObjects(), &timeHistoryCurvesData); populateTimeHistoryCurvesData(m_gridTimeHistoryCurves.childObjects(), &timeHistoryCurvesData);
for (size_t i = 0; i < timeHistoryCurvesData.timeSteps.size(); i++) //cases std::vector<CurvesData> exportData(2);
{
// Data for export
std::vector<time_t> expTimeSteps;
std::vector<CurveData> expCurveData;
out += "\n\n"; // Summary data for export
out += "Case: " + timeHistoryCurvesData.caseNames[i]; prepareCaseCurvesForExport(resamplingPeriod,
out += "\n"; ResampleAlgorithm::DATA_DECIDES,
summaryCurvesData,
&exportData[0]);
prepareCaseCurvesForExport(resamplingPeriod, // Time history data for export
ResampleAlgorithm::PERIOD_END, prepareCaseCurvesForExport(resamplingPeriod,
timeHistoryCurvesData.timeSteps[i], ResampleAlgorithm::PERIOD_END,
timeHistoryCurvesData.allCurveData[i], timeHistoryCurvesData,
&expTimeSteps, &exportData[1]);
&expCurveData);
appendToExportData(out, expTimeSteps, expCurveData); appendToExportData(out, exportData);
}
} }
// Pasted observed data // Pasted observed data
@ -347,21 +339,11 @@ QString RimSummaryPlot::asciiDataForPlotExport(DateTimePeriod resamplingPeriod)
CurvesData asciiCurvesData; CurvesData asciiCurvesData;
populateAsciiDataCurvesData(m_asciiDataCurves.childObjects(), &asciiCurvesData); populateAsciiDataCurvesData(m_asciiDataCurves.childObjects(), &asciiCurvesData);
for (size_t i = 0; i < asciiCurvesData.timeSteps.size(); i++) //cases for (size_t i = 0; i < asciiCurvesData.timeSteps.size(); i++)
{ {
// Data for export
std::vector<time_t> expTimeSteps;
std::vector<CurveData> expCurveData;
out += "\n\n"; out += "\n\n";
prepareCaseCurvesForExport(DateTimePeriod::NONE, appendToExportDataForCase(out, asciiCurvesData.timeSteps[i], asciiCurvesData.allCurveData[i]);
ResampleAlgorithm::NONE,
asciiCurvesData.timeSteps[i],
asciiCurvesData.allCurveData[i],
&expTimeSteps,
&expCurveData);
appendToExportData(out, expTimeSteps, expCurveData);
} }
} }
@ -1655,6 +1637,7 @@ void populateAsciiDataCurvesData(std::vector<RimAsciiDataCurve*> curves, CurvesD
if (casePosInList == cvf::UNDEFINED_SIZE_T) if (casePosInList == cvf::UNDEFINED_SIZE_T)
{ {
curvesData->caseNames.push_back("");
curvesData->timeSteps.push_back(curve->timeSteps()); curvesData->timeSteps.push_back(curve->timeSteps());
curvesData->allCurveData.push_back(std::vector<CurveData>({ curveData })); curvesData->allCurveData.push_back(std::vector<CurveData>({ curveData }));
} }
@ -1706,47 +1689,60 @@ void populateSummaryCurvesData(std::vector<RimSummaryCurve*> curves, CurvesData*
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm, void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
const std::vector<time_t> &timeSteps, const std::vector<CurveData>& curveData, const CurvesData& inputCurvesData,
std::vector<time_t>* exportTimeSteps, std::vector<CurveData>* exportCurveData) CurvesData* resultCurvesData)
{ {
RiaTimeHistoryCurveResampler resampler; RiaTimeHistoryCurveResampler resampler;
exportTimeSteps->clear(); resultCurvesData->clear();
exportCurveData->clear();
if (period != DateTimePeriod::NONE) if (period != DateTimePeriod::NONE)
{ {
for (auto& curveDataItem : curveData) for (int i = 0; i < inputCurvesData.caseNames.size(); i++)
{ {
resampler.setCurveData(curveDataItem.values, timeSteps); // Shortcuts to input data
auto& caseName = inputCurvesData.caseNames[i];
auto& caseTimeSteps = inputCurvesData.timeSteps[i];
auto& caseCurveData = inputCurvesData.allCurveData[i];
if (curveDataItem.address.hasAccumulatedData() || algorithm == ResampleAlgorithm::PERIOD_END) // Prepare result data
resultCurvesData->resamplePeriod = period;
//resultCurvesData->resampleAlgorithm = algorithm;
resultCurvesData->caseNames.push_back(caseName);
resultCurvesData->allCurveData.push_back(std::vector<CurveData>());
for (auto& curveDataItem : caseCurveData)
{ {
resampler.resampleAndComputePeriodEndValues(period); resampler.setCurveData(curveDataItem.values, caseTimeSteps);
}
else if (curveDataItem.address.hasAccumulatedData() || algorithm == ResampleAlgorithm::PERIOD_END)
{ {
resampler.resampleAndComputeWeightedMeanValues(period); resampler.resampleAndComputePeriodEndValues(period);
}
else
{
resampler.resampleAndComputeWeightedMeanValues(period);
}
auto cd = curveDataItem;
cd.values = resampler.resampledValues();
auto& currResultCurveDataList = resultCurvesData->allCurveData[i];
currResultCurveDataList.push_back(cd);
} }
auto cd = curveDataItem; resultCurvesData->timeSteps.push_back(resampler.resampledTimeSteps());
cd.values = resampler.resampledValues();
exportCurveData->push_back(cd);
} }
*exportTimeSteps = resampler.resampledTimeSteps();
} }
else else
{ {
*exportTimeSteps = timeSteps; *resultCurvesData = inputCurvesData;
*exportCurveData = curveData;
} }
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void appendToExportData(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData) void appendToExportDataForCase(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData)
{ {
for (size_t j = 0; j < timeSteps.size(); j++) //time steps & data points for (size_t j = 0; j < timeSteps.size(); j++) //time steps & data points
{ {
@ -1772,3 +1768,107 @@ void appendToExportData(QString& out, const std::vector<time_t>& timeSteps, cons
} }
} }
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void appendToExportData(QString& out, const std::vector<CurvesData>& curvesData)
{
CurvesData data = concatCurvesData(curvesData);
if (data.resamplePeriod != DateTimePeriod::NONE)
{
time_t minTimeStep = std::numeric_limits<time_t>::max();
time_t maxTimeStep = 0;
for (auto& timeSteps : data.timeSteps)
{
if (!timeSteps.empty())
{
if (timeSteps.front() < minTimeStep) minTimeStep = timeSteps.front();
if (timeSteps.back() > maxTimeStep) maxTimeStep = timeSteps.back();
}
}
auto allTimeSteps = RiaTimeHistoryCurveResampler::timeStepsFromTimeRange(data.resamplePeriod, minTimeStep, maxTimeStep);
out += "\n\n";
out += "Date and time";
for (size_t i = 0; i < data.caseNames.size(); i++)
{
for (size_t j = 0; j < data.allCurveData[i].size(); j++)
{
out += "\t" + data.allCurveData[i][j].name + " (" + data.caseNames[i] + ")";
}
}
out += "\n";
std::vector<int> currIndexes(data.caseNames.size());
for (auto& i : currIndexes) i = 0;
for (auto timeStep : allTimeSteps)
{
out += QDateTime::fromTime_t(timeStep).toUTC().toString("yyyy-MM-dd hh:mm:ss ");
for (size_t i = 0; i < data.caseNames.size(); i++) // cases
{
// Check is time step exists in curr case
int& currIndex = currIndexes[i];
bool timeStepExists = currIndex < data.timeSteps[i].size() && timeStep == data.timeSteps[i][currIndex];
for (size_t j = 0; j < data.allCurveData[i].size(); j++) // vectors
{
QString valueText;
if (timeStepExists)
{
valueText = QString::number(data.allCurveData[i][j].values[currIndex], 'g', 6);
}
else
{
valueText = "inf";
}
out += "\t" + valueText;
}
if (currIndex < data.timeSteps[i].size()) currIndex++;
}
out += "\n";
}
}
else
{
for (size_t i = 0; i < data.caseNames.size(); i++)
{
out += "\n\n";
out += "Case: " + data.caseNames[i];
out += "\n";
appendToExportDataForCase(out, data.timeSteps[i], data.allCurveData[i]);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CurvesData concatCurvesData(const std::vector<CurvesData>& curvesData)
{
CVF_ASSERT(!curvesData.empty());
DateTimePeriod period = curvesData.front().resamplePeriod;
CurvesData resultCurvesData;
resultCurvesData.resamplePeriod = period;
for (auto curvesDataItem : curvesData)
{
if (curvesDataItem.caseNames.empty()) continue;
CVF_ASSERT(curvesDataItem.resamplePeriod == period);
resultCurvesData.caseNames.insert(resultCurvesData.caseNames.end(), curvesDataItem.caseNames.begin(), curvesDataItem.caseNames.end());
resultCurvesData.timeSteps.insert(resultCurvesData.timeSteps.end(), curvesDataItem.timeSteps.begin(), curvesDataItem.timeSteps.end());
resultCurvesData.allCurveData.insert(resultCurvesData.allCurveData.end(), curvesDataItem.allCurveData.begin(), curvesDataItem.allCurveData.end());
}
return resultCurvesData;
}