From 330b4a319525b8a5fa7beb017a28268a7b2bd1f8 Mon Sep 17 00:00:00 2001 From: yuntang <123@qq.com> Date: Fri, 27 Jun 2025 15:34:58 +0800 Subject: [PATCH] 2025-06-27T15:34:56 --- src/data/lowesssmoother.cpp | 10 ++- src/data/pointcalculate.cpp | 124 ++++++++++++++++++++++++++++++++---- src/data/pointcalculate.h | 9 ++- src/logger/log.conf | 2 +- src/main.cpp | 25 +------- src/mainwindow.cpp | 69 +++++++------------- src/mainwindow.ui | 7 -- src/ui/centralwidget.cpp | 76 +++++++++------------- src/ui/centralwidget.h | 2 + src/ui/printpreviewform.cpp | 58 ++++++++++------- 10 files changed, 224 insertions(+), 158 deletions(-) diff --git a/src/data/lowesssmoother.cpp b/src/data/lowesssmoother.cpp index 88cb7e6..f7ffaaa 100644 --- a/src/data/lowesssmoother.cpp +++ b/src/data/lowesssmoother.cpp @@ -1,6 +1,8 @@ #include "lowesssmoother.h" #include +#include "logger.h" + namespace Lowess { void validateConfig(const Config& config) { @@ -54,10 +56,14 @@ std::vector smooth( validateConfig(config); if (x.size() != y.size()) { - throw std::invalid_argument("x and y must have the same size"); +// throw std::invalid_argument("x and y must have the same size"); + logde<<"x and y must have the same size."; + return std::vector(); } if (x.size() < 2) { - throw std::invalid_argument("At least 2 data points required"); +// throw std::invalid_argument("At least 2 data points required"); + logde<<"At least 2 data points required."; + return std::vector(); } size_t n = x.size(); diff --git a/src/data/pointcalculate.cpp b/src/data/pointcalculate.cpp index 37e147f..907077d 100644 --- a/src/data/pointcalculate.cpp +++ b/src/data/pointcalculate.cpp @@ -72,7 +72,7 @@ QPointF PointCalculate::getPeakPoint(){ _peakPoint = uniquePeak; - logde<<"peakPoint:"<<_peakPoint.x()<<","<<_peakPoint.y(); + // logde<<"peakPoint:"<<_peakPoint.x()<<","<<_peakPoint.y(); return uniquePeak; } @@ -181,21 +181,21 @@ QPointF PointCalculate::findClosestPointByX(float x) { void PointCalculate::setRegionPointX(const float left, const float right) { - logde<<"dataVtr size:"<<_dataVtr.size(); - logde<<"select point param left,right:"< PointCalculate::getPeakPointGroup() @@ -211,9 +211,14 @@ QVector PointCalculate::getPeakPointGroup() return pointVtr; } -float PointCalculate::calculateArea() { +float PointCalculate::calculateArea(const double x1,const double x2) { //getPoint group QVector points = getPeakPointGroup(); +#if 1 + if(_axisMode == AxisMode::DoubleY){ + points = getPeakPointGroupByTime(x1,x2); + } +#endif logde<<"points size:"< PointCalculate::getNearbyPointGroupByX(const float targetX) if(tmpPointVtr.size() > conCount){ targetPointVtr = QVector(tmpPointVtr.end() - conCount, tmpPointVtr.end()); }else{ - targetPointVtr = tmpPointVtr; + targetPointVtr = tmpPointVtr; } } } @@ -1151,3 +1167,89 @@ std::pair PointCalculate::calculateMedianOIT(){ double PointCalculate::calculateDistance(const QPointF& p1, const QPointF& p2) { return std::sqrt(std::pow(p2.x() - p1.x(), 2) + std::pow(p2.y() - p1.y(), 2)); } + +QVector PointCalculate::getDataInXRangeByTime(const float x1, const float x2) +{ + QVector targetVtr; + for(const Global::ExperimentData &ed : _dataVtr) { + if(x1 < ed.runTime && ed.runTime < x2){ + targetVtr.push_back(ed); + }else if (ed.runTime > x2){ + break; + } + + } + + return targetVtr; +} + + +QVector PointCalculate::getPeakPointGroupByTime(const double x1, const double x2) +{ + // modify select point. + ExperimentData edX1 = getClosestDataByTime(x1); + ExperimentData edX2 = getClosestDataByTime(x2); + + _leftSelectedPoint = QPointF(edX1.runTime,edX1.dsc); + _rightSelectedPoint = QPointF(edX2.runTime,edX2.dsc); + + // 焓值计算还得用样品温度作为x值。 + QVector pointVtr; + for(Global::ExperimentData& ed:_dataVtr) { + if(ed.sampleTemp >= edX1.sampleTemp && + ed.sampleTemp <= edX2.sampleTemp){ + + pointVtr.push_back(QPointF(ed.sampleTemp,ed.dsc)); + } + } + + return pointVtr; +} + + +QPair PointCalculate::getSelectedPoints() +{ + return qMakePair(_leftSelectedPoint,_rightSelectedPoint); +} + +QPointF PointCalculate::getPeakPointByTime() +{ + int n = _dataVtr.size(); + + if (n < 3) { + return QPointF(); // 至少需要三个点才能找到波峰 + } + + QPointF uniquePeak; + float maxDiff = -std::numeric_limits::infinity(); + + for (int i = 0; i < n; ++i) { + const float currentX = _dataVtr.at(i).runTime; + const float currentY = _dataVtr.at(i).dsc; + + if (currentX < _leftSelectedPoint.x()) { + continue; + } + if (currentX > _rightSelectedPoint.x()) { + break; + } + + // 计算当前点与左选择点 y 值的差值 + float diffLeft = std::abs(currentY - _leftSelectedPoint.y()); + // 计算当前点与右选择点 y 值的差值 + float diffRight = std::abs(currentY - _rightSelectedPoint.y()); + // 取两个差值中的较大值 + float currentDiff = std::max(diffLeft, diffRight); + + if (currentDiff > maxDiff) { + maxDiff = currentDiff; + uniquePeak = QPointF(currentX, currentY); + } + } + + _peakPoint = uniquePeak; + + // logde<<"peakPoint:"<<_peakPoint.x()<<","<<_peakPoint.y(); + + return uniquePeak; +} diff --git a/src/data/pointcalculate.h b/src/data/pointcalculate.h index 9262ab7..882c8ef 100644 --- a/src/data/pointcalculate.h +++ b/src/data/pointcalculate.h @@ -19,6 +19,8 @@ QPair getMinAndMaxOfDSC(); QPair getMinAndMaxOfAxis(const float min,const float max); QVector getDataInXRange(const float, const float); +QVector getDataInXRangeByTime(const float, const float); + QVector getPointVtrInXRange(const float, const float); void setRegionPointX(const float,const float); @@ -31,8 +33,11 @@ QVector getNearbyPointGroupByX(const float); QPointF getClosestPointByY(const double left,const double right,const double valueY); QPointF getPeakPoint(); +QPointF getPeakPointByTime(); QPair getMaxMinValue(); +QPair getSelectedPoints(); + // According to the value of plot x axis witch of temperature value. QPair getTheMaximumAndMinimumValuesOfTime( const double min,const double max); @@ -42,7 +47,7 @@ QPair calculateStartAndEndData(); QPair calculateOITStartAndEndDataByTime(const double x1,const double x2); -float calculateArea(); +float calculateArea(const double x1,const double x2); double obtainTimeValueBasedOnTemperatureValue(const double sampleTemp); ExperimentData findOnSetDataByTemperature(const double x1,const double x2); @@ -102,6 +107,8 @@ QPair calculateMaxDiffDataByTime( QPointF calculateIntersection(const QPointF p1,const QPointF p2, const QPointF p3, const QPointF p4); QVector getPeakPointGroup(); +QVector getPeakPointGroupByTime(const double,const double); + std::vector movingAverage(const std::vector& data, int windowSize); QVector movingAveragePoint(const QVector& data, int windowSize); diff --git a/src/logger/log.conf b/src/logger/log.conf index a068a5f..544f2b9 100644 --- a/src/logger/log.conf +++ b/src/logger/log.conf @@ -2,7 +2,7 @@ ENABLED = true TO_FILE = true TO_STANDARD_OUTPUT = true - FORMAT = "[%datetime] %msg" + FORMAT = "[%datetime] [%func] %msg" FILENAME = "log-sdk/%datetime{%Y%M%d}.log" MILLISECONDS_WIDTH = 3 PERFORMANCE_TRACKING = false diff --git a/src/main.cpp b/src/main.cpp index 1e59566..09da339 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,7 +15,7 @@ int main(int argc, char *argv[]) { -// system("chcp 65001"); + // system("chcp 65001"); QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForLocale(codec); @@ -24,24 +24,8 @@ int main(int argc, char *argv[]) // ConfigHandler::reader(); -#if 0 - logde<<"config,instrument coefficient:" - < smoothDataVtr; - QString objectName; - QCPCurve ** curvePtrPtr; - - // 当前数据为实验数据时,需要把所有的当前实验数据都尽心平滑处理。 - if(!Global::_curveExperimentDataVtr.empty()){ - for(auto & item:Global::_curveExperimentDataVtr){ - if(_centralWidget->isCurrentCurve(item.curve)){ - smoothDataVtr = smoothnessDetail(level,item.dataVtr); - - item.smoothDataVtr = smoothDataVtr; - - objectName = Global::ObjectNameExperiemnt; - curvePtrPtr = &item.curve; - } - } - }else{ - for(Global::CurveFileData &cfd :Global::_curveFileDataVtr){ - for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){ - if(_centralWidget->isCurrentCurve(pti.curve)){ - smoothDataVtr = smoothnessDetail(level,pti.dataVtr); - - pti.smoothDataVtr = smoothDataVtr; - - objectName = cfd.fileName; - curvePtrPtr = &pti.curve; - } - } - } - } - - // - _centralWidget->deleteCurrentCurve(); - - // - QString wholeObjectName = Global::ObjectNameSmooth + Global::Separator + objectName; - _centralWidget->addCurveData(smoothDataVtr,wholeObjectName); - - *curvePtrPtr = _centralWidget->getCurrentCurve(); -#endif + logde<<"smoothness..."; + slotUpdateStatusbarMsg("数据平滑计算中..."); if(!Global::_curveExperimentDataVtr.empty()){ // 当前数据为实验数据时,需要把所有的当前实验数据都进行平滑处理。 @@ -373,7 +331,8 @@ void MainWindow::smoothness(const int level) // 添加所有平滑后的curve. for(auto & item:Global::_curveExperimentDataVtr){ item.smoothDataVtr = smoothnessDetail(level,item.dataVtr); - item.curve = _centralWidget->addCurveData(item.smoothDataVtr,Global::ObjectNameExperiemnt); + item.curve = _centralWidget->addCurveData(item.smoothDataVtr, + Global::ObjectNameExperiemnt); } }else{ // 当前数据为文件分析数据时,需要把当前文件下的所有数据都进行平滑处理。 @@ -412,12 +371,28 @@ QVector MainWindow::smoothnessDetail(const int level,con y.push_back(ed.dsc); } + slotUpdateStatusbarMsg("数据平滑计算中..."); + + QVector resultVtr; logde<<"smooth start..."; + logde<<"x,y size:"<statusbar->showMessage("数据平滑计算中..."); + ui->statusbar->showMessage("数据平滑计算中..."); + ui->statusbar->showMessage("数据平滑计算中..."); + ui->statusbar->showMessage("数据平滑计算中..."); + std::vector yest = Lowess::smooth(x, y, config); + if(yest.empty()){ + slotUpdateStatusbarMsg("数据平滑完成."); + return resultVtr; + } + + slotUpdateStatusbarMsg("数据平滑完成."); + logde<<"smooth end..."; // result data vector. - QVector resultVtr; for(int i = 0; i < x.size();i++){ Global::ExperimentData ed; @@ -610,6 +585,8 @@ void MainWindow::on_actionPeakSynthesisAnalysis_triggered() void MainWindow::on_actionClearAllData_triggered() { + slotUpdateStatusbarMsg(""); + _rightWidget->hide(); _centralWidget->clearAllData(); } diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 35a3a0f..90e0d5b 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -92,12 +92,6 @@ - - - 语言 - - - 帮助 @@ -116,7 +110,6 @@ - diff --git a/src/ui/centralwidget.cpp b/src/ui/centralwidget.cpp index d484406..b960bf7 100644 --- a/src/ui/centralwidget.cpp +++ b/src/ui/centralwidget.cpp @@ -140,6 +140,9 @@ void CentralWidget::deleteAllExperimentCurve() QCPCurve* CentralWidget::addCurveData( const QVector &dataVtr,const QString objectName) { + logde<<"addCurveData..."; + logde<<"data vtr size:"<setData(tVtr, xVtr, yVtr); _currentCurve->setSelectable(QCP::stWhole); // 设置曲线可选 _currentCurve->setLineStyle(QCPCurve::lsLine); // 线性连接 + _currentCurve->setVisible(true); _currentCurve->setObjectName(objectName); @@ -172,6 +176,7 @@ QCPCurve* CentralWidget::addCurveData( // Axis x is time value. minMaxXAxisPair = PointCalculate::getMinAndMaxOfRunTime(); } +#if 1 QPairnewXAxisPair = PointCalculate::getMinAndMaxOfAxis( minMaxXAxisPair.first,minMaxXAxisPair.second); _customPlot->xAxis->setRange(newXAxisPair.first, newXAxisPair.second); @@ -181,6 +186,7 @@ QCPCurve* CentralWidget::addCurveData( minMaxYAxisPair.first,minMaxYAxisPair.second); _customPlot->yAxis->setRange(newYAxisPair.first , newYAxisPair.second); +#endif // Add analysis operation data. #if 0 @@ -194,6 +200,7 @@ QCPCurve* CentralWidget::addCurveData( // Refresh ui. _customPlot->replot(); + _customPlot->update(); return _currentCurve; } @@ -1140,18 +1147,6 @@ void CentralWidget::drawText(const QPointF point, const QString text,const QStri void CentralWidget::fillGraph(const double x1, const double x2,const QString objectName) { -#if 0 - double y1 = PointCalculate::getClosestPointByX(x1).y(); - double y2 = PointCalculate::getClosestPointByX(x2).y(); - - QVector xVtr,yVtr; - xVtr.push_back(x1); - xVtr.push_back(x2); - - yVtr.push_back(y1); - yVtr.push_back(y2); -#endif - Global::ExperimentData x1Ed = PointCalculate::getClosestDataByTemperature(x1); Global::ExperimentData x2Ed = PointCalculate::getClosestDataByTemperature(x2); QVector xVtr,yVtr; @@ -1169,6 +1164,10 @@ void CentralWidget::fillGraph(const double x1, const double x2,const QString obj xVtr.push_back(x1Ed.runTime); xVtr.push_back(x2Ed.runTime); + + yVtr.clear(); + yVtr.push_back(x1Ed.dsc); + yVtr.push_back(x2Ed.dsc); } QCPGraph *mainGraph = _customPlot->addGraph(); @@ -1178,6 +1177,9 @@ void CentralWidget::fillGraph(const double x1, const double x2,const QString obj // QVector curveDataVtr = PointCalculate::getDataInXRange(x1,x2); + if(_axisMode == AxisMode::DoubleY){ + curveDataVtr = PointCalculate::getDataInXRangeByTime(x1,x2); + } QCPGraph *fillGraph = _customPlot->addGraph(); QVector fillX, fillY; @@ -1197,6 +1199,7 @@ void CentralWidget::fillGraph(const double x1, const double x2,const QString obj fillGraph->setBrush(QBrush(Qt::green, Qt::SolidPattern)); fillGraph->setChannelFillGraph(mainGraph); + // ItemManager::addTemporaryQCPGraph(mainGraph,objectName); ItemManager::addTemporaryQCPGraph(fillGraph,objectName); @@ -1370,7 +1373,6 @@ void CentralWidget::calculateAnalysisResult( const AnalysisMode mode,const double x1,const double x2,const QString objectName) { logde<<"calculateAnalysisResult..."; - logde<<"x1,x2:"< startEndPointPair = @@ -1494,20 +1490,13 @@ void CentralWidget::calculateAnalysisResult( QString str; if(_axisMode == AxisMode::DoubleY){ - double peakPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(peakPoint.x()); - double startPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(startEndPointPair.first.x()); - double endPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(startEndPointPair.second.x()); + QPair selectedPointsPair = PointCalculate::getSelectedPoints(); - str = PointCalculate::textFormatPeakPointWithTime( + str = PointCalculate::textFormatPeakPointWithTime( enthalpyValue, - peakPointTime, - startPointTime, - endPointTime); - - Global::ExperimentData peakPointEd = - PointCalculate::getClosestDataByTemperature(peakPoint.x()); - - peakPoint = QPointF(peakPointEd.runTime,peakPointEd.dsc); + peakPoint.x(), + selectedPointsPair.first.x(), + selectedPointsPair.second.x()); drawText(peakPoint,str,objectName); } @@ -1705,6 +1694,7 @@ void CentralWidget::setAxisMode(AxisMode mode) } } +#if 0 void CentralWidget::peakSynthesisDoubleAxisY(const double, const double,const QString objectName) { @@ -1723,12 +1713,6 @@ void CentralWidget::peakSynthesisSingleAxisY(const double x1, const double x2,co }else{ for(Global::CurveFileData& cfd:Global::_curveFileDataVtr){ for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){ - -#if 0 - if(_currentCurve && _currentCurve == pti.curve){ - sampleWeight = cfd.ei.sampleWeight.toDouble(); - } -#endif if(_currentCurve){ if(_currentCurve == pti.curve){ sampleWeight = cfd.ei.sampleWeight.toDouble(); @@ -1746,8 +1730,7 @@ void CentralWidget::peakSynthesisSingleAxisY(const double x1, const double x2,co sampleWeight = 1; } - double enthalpyValue = PointCalculate::calculateArea() / sampleWeight; - + double enthalpyValue = PointCalculate::calculateArea(x1,x2) / sampleWeight; logde<<"enthalpyValue:"<setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables); + Global::_mode = Global::Mode::Analysis; clearData(ClearDataMode::All); } diff --git a/src/ui/centralwidget.h b/src/ui/centralwidget.h index 8ae0875..bf02b44 100644 --- a/src/ui/centralwidget.h +++ b/src/ui/centralwidget.h @@ -124,8 +124,10 @@ private: void setAxisMode(Global::AxisMode mode); +#if 0 void peakSynthesisDoubleAxisY(const double,const double,const QString objectName); void peakSynthesisSingleAxisY(const double,const double,const QString objectName); +#endif private: AnalysisOperationRecorder::AnalysisMode _analysisMode; LocalCustomPlot *_customPlot; diff --git a/src/ui/printpreviewform.cpp b/src/ui/printpreviewform.cpp index 0029313..5e7b2f6 100644 --- a/src/ui/printpreviewform.cpp +++ b/src/ui/printpreviewform.cpp @@ -46,6 +46,8 @@ void PrintPreviewForm::setPixmap(const QPixmap &pixmap) void PrintPreviewForm::slotPaintRequested(QPrinter *printer) { + const int ConTextHeight = 100; + printer->setOrientation(QPrinter::Landscape); QPainter painter(printer); @@ -64,35 +66,31 @@ void PrintPreviewForm::slotPaintRequested(QPrinter *printer) QRect pageRect = printer->pageRect(); qDebug()<<"rect:"<& phaseTotalVtr = Global::_curveFileDataVtr.first().phaseTotalVtr; @@ -168,7 +180,7 @@ void PrintPreviewForm::slotPaintRequested(QPrinter *printer) } - painter.drawText(phaseInfoRect, Qt::AlignLeft|Qt::AlignVCenter, phaseInfoStr); + painter.drawText(phaseInfoRect, Qt::AlignLeft|Qt::AlignTop, phaseInfoStr); }