2025-06-26T17:30:00
This commit is contained in:
parent
3551a87337
commit
ca1186c9b1
BIN
experiment_data/sample_data/ABS.xlsx
Normal file
BIN
experiment_data/sample_data/ABS.xlsx
Normal file
Binary file not shown.
@ -9,7 +9,7 @@ CONFIG+=precompile_header
|
||||
PRECOMPILED_HEADER=stable.h
|
||||
|
||||
#
|
||||
VERSION = 1.0.8
|
||||
VERSION = 1.1.0
|
||||
# 设置目标文件名,包含版本号
|
||||
TARGET = DSCAnalysisTool_$${VERSION}
|
||||
|
||||
|
@ -619,16 +619,22 @@ QVector<QPointF> PointCalculate::getNearbyPointGroupByX(const float targetX)
|
||||
if (diff < minDiff) {
|
||||
minDiff = diff;
|
||||
|
||||
if(tmpPointVtr.size() > conCount){
|
||||
targetPointVtr = QVector<QPointF>(tmpPointVtr.end() - conCount, tmpPointVtr.end());
|
||||
}else{
|
||||
targetPointVtr = tmpPointVtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return targetPointVtr;
|
||||
}
|
||||
|
||||
// 计算两点之间的斜率
|
||||
double PointCalculate::calculateSlope(double x1, double y1, double x2, double y2) {
|
||||
if(x1 == x2){
|
||||
return 0.0;
|
||||
}
|
||||
return (y2 - y1) / (x2 - x1);
|
||||
}
|
||||
|
||||
@ -659,6 +665,9 @@ QMap<double, PointCalculate::Line> PointCalculate::calculateTangentLine(
|
||||
for (double xInflection : inflectionPointsX) {
|
||||
int i = std::distance(x.begin(), std::find(x.begin(), x.end(), xInflection));
|
||||
double slope = calculateSlope(x[i - 1], y[i - 1], x[i + 1], y[i + 1]);
|
||||
if(slope == 0.0){
|
||||
continue;
|
||||
}
|
||||
double yInflection = y[i];
|
||||
double intercept = yInflection - slope * xInflection;
|
||||
tangentLines[xInflection] = {slope, intercept};
|
||||
@ -1137,3 +1146,8 @@ std::pair<bool, Global::ExperimentData> PointCalculate::calculateMedianOIT(){
|
||||
return std::make_pair(true, sortedData[n/2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ QPointF getIntersection(const Line& line1, const Line& line2);
|
||||
double calculateSlope(double x1, double y1, double x2, double y2) ;
|
||||
QVector<double> findInflectionPoints(const QVector<double>& x, const QVector<double>& y) ;
|
||||
QMap<double, Line> calculateTangentLine(const QVector<double>& x, const QVector<double>& y) ;
|
||||
double calculateDistance(const QPointF& p1, const QPointF& p2);
|
||||
|
||||
//private
|
||||
void updateStartEndPoint();
|
||||
@ -104,6 +105,7 @@ QVector<QPointF> getPeakPointGroup();
|
||||
std::vector<float> movingAverage(const std::vector<float>& data, int windowSize);
|
||||
QVector<QPointF> movingAveragePoint(const QVector<QPointF>& data, int windowSize);
|
||||
|
||||
|
||||
extern QVector<Global::ExperimentData> _dataVtr;
|
||||
extern QPointF _peakPoint;
|
||||
extern QPointF _leftSelectedPoint,_rightSelectedPoint;
|
||||
|
@ -127,6 +127,8 @@ private:
|
||||
void smoothness(const int level);
|
||||
QVector<Global::ExperimentData> smoothnessDetail(const int level,const QVector<Global::ExperimentData>&);
|
||||
void smoothnessExperimentData(const int level);
|
||||
|
||||
|
||||
private:
|
||||
bool _manuallyStopTheExperimentFlag;
|
||||
Ui::MainWindow *ui;
|
||||
|
@ -617,7 +617,7 @@ void CentralWidget::slotSelectionChangedByUser()
|
||||
|
||||
void CentralWidget::uiLoadXlsxFileData()
|
||||
{
|
||||
#if 0
|
||||
#if 1
|
||||
// Set axis.
|
||||
_customPlot->yAxis->setVisible(true);
|
||||
_customPlot->yAxis->setLabel(AxisDSC);
|
||||
@ -632,6 +632,8 @@ void CentralWidget::uiLoadXlsxFileData()
|
||||
_customPlot->yAxis2->setVisible(true);
|
||||
_customPlot->yAxis2->setLabel(AxisTemperature);
|
||||
}
|
||||
|
||||
_customPlot->replot();
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
@ -759,12 +761,19 @@ void CentralWidget::uiLoadXlsxFileData()
|
||||
|
||||
void CentralWidget::glassTransitionHandle(const double x1,const double x2,const QString objectName)
|
||||
{
|
||||
QVector<double> tickPositions = _customPlot->xAxis->tickVector();
|
||||
double step = tickPositions.at(1) - tickPositions.at(0);
|
||||
logde<<"glassTransitionHandle step:"<<step;
|
||||
double extendedLineStep = step / 2;
|
||||
|
||||
|
||||
QPointF point1 = PointCalculate::getClosestPointByX(x1);
|
||||
QPointF point2 = PointCalculate::getClosestPointByX(x2);
|
||||
|
||||
logde<<"point1:"<<point1.x()<<","<<point1.y();
|
||||
logde<<"point2:"<<point2.x()<<","<<point2.y();
|
||||
|
||||
//获取与选择点接近的10个点
|
||||
QVector<QPointF> point1Vtr = PointCalculate::getNearbyPointGroupByX(point1.x());
|
||||
QVector<QPointF> point2Vtr = PointCalculate::getNearbyPointGroupByX(point2.x());
|
||||
|
||||
@ -777,16 +786,15 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
|
||||
PointCalculate::Line line1 = calculateLinearRegression(xVtr,yVtr);
|
||||
|
||||
#if 1
|
||||
///line1
|
||||
// QVector<double> xVtr,yVtr;
|
||||
//line1
|
||||
xVtr.clear();
|
||||
yVtr.clear();
|
||||
|
||||
xVtr.push_back(point1.x());
|
||||
yVtr.push_back(point1.y());
|
||||
|
||||
xVtr.push_back(point1.x() + 10);
|
||||
double y1 = line1.slope * (point1.x() + 10) + line1.intercept;
|
||||
xVtr.push_back(point1.x() + extendedLineStep);
|
||||
double y1 = line1.slope * (point1.x() + extendedLineStep) + line1.intercept;
|
||||
yVtr.push_back(y1);
|
||||
|
||||
QCPGraph *lineGraph1 = _customPlot->addGraph();
|
||||
@ -797,9 +805,9 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
|
||||
QPen pen;
|
||||
pen.setColor(Qt::darkGreen);
|
||||
lineGraph1->setPen(pen);
|
||||
|
||||
#endif
|
||||
|
||||
//line2
|
||||
xVtr.clear();
|
||||
yVtr.clear();
|
||||
for(QPointF &p:point2Vtr){
|
||||
@ -809,8 +817,7 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
|
||||
|
||||
PointCalculate::Line line2 = calculateLinearRegression(xVtr,yVtr);
|
||||
|
||||
#if 1
|
||||
///line2
|
||||
#if 0
|
||||
QVector<double> xVtr2,yVtr2;
|
||||
xVtr2.push_back(point2.x());
|
||||
yVtr2.push_back(point2.y());
|
||||
@ -846,18 +853,7 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
|
||||
PointCalculate::Line targetLine;
|
||||
double maxSlopeAbs = 0.0; // 初始化最大斜率绝对值为0
|
||||
|
||||
#if 0
|
||||
for (auto it = tangentLines.begin(); it != tangentLines.end(); ++it) {
|
||||
if (std::fabs(it.value().slope) > maxSlopeAbs) {
|
||||
maxSlopeAbs = std::fabs(it.value().slope); // 更新最大斜率绝对值
|
||||
|
||||
targetX = it.key();
|
||||
targetLine = it.value();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// new method
|
||||
//
|
||||
for (auto it = tangentLines.begin(); it != tangentLines.end(); ++it) {
|
||||
if (std::fabs(it.value().slope) > maxSlopeAbs) {
|
||||
maxSlopeAbs = std::fabs(it.value().slope); // 更新最大斜率绝对值
|
||||
@ -881,26 +877,17 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
|
||||
prePoint = pointVtr[index - 1];
|
||||
lastPoint = pointVtr[index + 1];
|
||||
|
||||
|
||||
targetLine.slope = PointCalculate::calculateSlope(lastPoint.x(),lastPoint.y(),prePoint.x(),prePoint.y());
|
||||
targetLine.intercept = currentPoint.y() - targetLine.slope * currentPoint.x();
|
||||
//
|
||||
#if 1
|
||||
|
||||
QPointF intersection1 = PointCalculate::getIntersection(targetLine,line1);
|
||||
QPointF intersection2 = PointCalculate::getIntersection(targetLine,line2);
|
||||
|
||||
// graph 3
|
||||
// line 3
|
||||
xVtr.clear();
|
||||
yVtr.clear();
|
||||
|
||||
#if 0
|
||||
xVtr.push_back(point1.x());
|
||||
yVtr.push_back(point1.y());
|
||||
|
||||
xVtr.push_back(point1.x());
|
||||
yVtr.push_back(point1.y());
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
xVtr.push_back(intersection1.x());
|
||||
yVtr.push_back(intersection1.y());
|
||||
@ -914,12 +901,50 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
|
||||
lineGraph3->setPen(pen);
|
||||
|
||||
ItemManager::addTemporaryQCPGraph(lineGraph3,objectName);
|
||||
|
||||
_customPlot->replot();
|
||||
|
||||
// draw line 2
|
||||
QVector<double> xVtr2,yVtr2;
|
||||
xVtr2.push_back(point2.x());
|
||||
yVtr2.push_back(point2.y());
|
||||
|
||||
#if 0
|
||||
xVtr2.push_back(point2.x() - 10);
|
||||
double y2 = line2.slope * (point2.x() - 10) + line2.intercept;
|
||||
yVtr2.push_back(y2);
|
||||
#endif
|
||||
|
||||
double minDistance = PointCalculate::calculateDistance(point2,intersection2);
|
||||
// 计算延长线另一个端点,使线长度超过minDistance.
|
||||
double halfOfExtendedLineStep = extendedLineStep /2;
|
||||
double distance = 0.0;
|
||||
int power = 0;
|
||||
QPointF line2Endpoint;
|
||||
while(distance < minDistance){
|
||||
power++;
|
||||
|
||||
line2Endpoint.setX(point2.x() - halfOfExtendedLineStep * power);
|
||||
line2Endpoint.setY(line2.slope * (point2.x() - halfOfExtendedLineStep * power)
|
||||
+ line2.intercept);
|
||||
|
||||
distance = PointCalculate::calculateDistance(
|
||||
point2,line2Endpoint);
|
||||
}
|
||||
|
||||
xVtr2.push_back(line2Endpoint.x());
|
||||
yVtr2.push_back(line2Endpoint.y());
|
||||
|
||||
QCPGraph *lineGraph2 = _customPlot->addGraph();
|
||||
lineGraph2->setData(xVtr2, yVtr2);
|
||||
lineGraph2->setPen(pen);
|
||||
|
||||
ItemManager::addTemporaryQCPGraph(lineGraph2,objectName);
|
||||
|
||||
_customPlot->replot();
|
||||
|
||||
// point value
|
||||
double averageY = (point1.y() + point2.y()) / 2;
|
||||
double averageY = (intersection1.y() + intersection2.y()) / 2;
|
||||
|
||||
QPointF averagePoint = PointCalculate::getClosestPointByY(point1.x(),point2.x(),averageY);
|
||||
|
||||
@ -1137,6 +1162,9 @@ void CentralWidget::fillGraph(const double x1, const double x2,const QString obj
|
||||
yVtr.push_back(x2Ed.dsc);
|
||||
|
||||
if(_axisMode == AxisMode::DoubleY){
|
||||
x1Ed = PointCalculate::getClosestDataByTime(x1);
|
||||
x2Ed = PointCalculate::getClosestDataByTime(x2);
|
||||
|
||||
xVtr.clear();
|
||||
|
||||
xVtr.push_back(x1Ed.runTime);
|
||||
@ -1343,11 +1371,14 @@ void CentralWidget::calculateAnalysisResult(
|
||||
{
|
||||
logde<<"calculateAnalysisResult...";
|
||||
|
||||
logde<<"x1,x2:"<<x1<<","<<x2;
|
||||
|
||||
switch (mode) {
|
||||
case AnalysisMode::NumericalLabel:
|
||||
{
|
||||
// QPointF selectPoint = PointCalculate::getClosestPointByX(x1);
|
||||
|
||||
QPointF selectPoint;
|
||||
QString str;
|
||||
if(_axisMode == AxisMode::SingleY){
|
||||
Global::ExperimentData ed = PointCalculate::getClosestDataByTemperature(x1);
|
||||
|
||||
if(Global::isZero(ed.dsc)){
|
||||
@ -1355,10 +1386,16 @@ void CentralWidget::calculateAnalysisResult(
|
||||
return;
|
||||
}
|
||||
|
||||
QPointF selectPoint(ed.sampleTemp,ed.dsc);
|
||||
QString str = PointCalculate::textFormatNumbericalLabel(selectPoint);
|
||||
if(_axisMode == AxisMode::DoubleY){
|
||||
selectPoint.setX(ed.runTime);
|
||||
selectPoint = QPointF(ed.sampleTemp,ed.dsc);
|
||||
str = PointCalculate::textFormatNumbericalLabel(selectPoint);
|
||||
}else{
|
||||
Global::ExperimentData ed = PointCalculate::getClosestDataByTime(x1);
|
||||
|
||||
if(Global::isZero(ed.dsc)){
|
||||
QMessageBox::warning((QWidget*)this->parent(), "warnning", "曲线选择错误.");
|
||||
return;
|
||||
}
|
||||
selectPoint = QPointF(ed.runTime,ed.dsc);
|
||||
str = PointCalculate::textFormatNumbericalLabelWithTime(selectPoint);
|
||||
}
|
||||
|
||||
@ -1405,7 +1442,9 @@ void CentralWidget::calculateAnalysisResult(
|
||||
}
|
||||
case AnalysisMode::PeakSynthesisAnalysis:
|
||||
{
|
||||
|
||||
fillGraph(x1,x2,objectName);
|
||||
return;
|
||||
|
||||
PointCalculate::setRegionPointX(x1,x2);
|
||||
|
||||
@ -1501,7 +1540,6 @@ void CentralWidget::calculateAnalysisResult(
|
||||
{
|
||||
glassTransitionHandle(x1,x2,objectName);
|
||||
|
||||
//
|
||||
break;
|
||||
}
|
||||
case AnalysisMode::OnsetTemperaturePoint:{
|
||||
@ -1644,6 +1682,7 @@ void CentralWidget::setAxisMode(AxisMode mode)
|
||||
if(_axisMode != mode){
|
||||
_axisMode = mode;
|
||||
|
||||
#if 0
|
||||
// Set axis.
|
||||
_customPlot->yAxis->setVisible(true);
|
||||
_customPlot->yAxis->setLabel(AxisDSC);
|
||||
@ -1660,11 +1699,109 @@ void CentralWidget::setAxisMode(AxisMode mode)
|
||||
}
|
||||
|
||||
_customPlot->replot();
|
||||
#endif
|
||||
|
||||
uiLoadXlsxFileData();
|
||||
}
|
||||
}
|
||||
|
||||
void CentralWidget::peakSynthesisDoubleAxisY(const double, const double,const QString objectName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CentralWidget::peakSynthesisSingleAxisY(const double x1, const double x2,const QString objectName)
|
||||
{
|
||||
fillGraph(x1,x2,objectName);
|
||||
|
||||
PointCalculate::setRegionPointX(x1,x2);
|
||||
|
||||
//enthalpy
|
||||
double sampleWeight = 1.0f;
|
||||
if(Global::_curveFileDataVtr.empty()){
|
||||
sampleWeight = Global::converStrToDouble(Global::_experimentInfo.sampleWeight);
|
||||
}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();
|
||||
}else{
|
||||
}
|
||||
}else{
|
||||
// logde<<"current curve nullptr.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sampleWeight <= 0){
|
||||
logde<<"sample weight set value 1,"<<sampleWeight;
|
||||
sampleWeight = 1;
|
||||
}
|
||||
|
||||
double enthalpyValue = PointCalculate::calculateArea() / sampleWeight;
|
||||
|
||||
logde<<"enthalpyValue:"<<enthalpyValue;
|
||||
|
||||
// peak
|
||||
QPointF peakPoint = PointCalculate::getPeakPoint();
|
||||
|
||||
// start point and end point
|
||||
QPair<QPointF, QPointF> startEndPointPair =
|
||||
PointCalculate::calculateStartAndEndPoint();
|
||||
|
||||
logde<<"start,end:"<<startEndPointPair.first.x()<<","
|
||||
<<startEndPointPair.second.x();
|
||||
|
||||
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());
|
||||
|
||||
str = PointCalculate::textFormatPeakPointWithTime(
|
||||
enthalpyValue,
|
||||
peakPointTime,
|
||||
startPointTime,
|
||||
endPointTime);
|
||||
|
||||
Global::ExperimentData peakPointEd =
|
||||
PointCalculate::getClosestDataByTemperature(peakPoint.x());
|
||||
|
||||
peakPoint = QPointF(peakPointEd.runTime,peakPointEd.dsc);
|
||||
|
||||
drawText(peakPoint,str,objectName);
|
||||
}
|
||||
else if(Global::_displayTimeValue){
|
||||
double peakPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(peakPoint.x());
|
||||
double startPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(startEndPointPair.first.x());
|
||||
double endPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(startEndPointPair.second.x());
|
||||
|
||||
str = PointCalculate::textFormatPeakPointWithTime(
|
||||
enthalpyValue,
|
||||
peakPointTime,
|
||||
startPointTime,
|
||||
endPointTime);
|
||||
|
||||
drawText(peakPoint,str,objectName);
|
||||
|
||||
}else{
|
||||
str = PointCalculate::textFormatPeakPoint(
|
||||
enthalpyValue,
|
||||
peakPoint.x(),
|
||||
startEndPointPair.first.x(),
|
||||
startEndPointPair.second.x());
|
||||
drawText(peakPoint,str,objectName);
|
||||
}
|
||||
}
|
||||
|
||||
void CentralWidget::clearAllData()
|
||||
{
|
||||
Global::_mode = Global::Mode::Analysis;
|
||||
|
@ -123,6 +123,9 @@ private:
|
||||
const int step,const QString objectName);
|
||||
|
||||
void setAxisMode(Global::AxisMode mode);
|
||||
|
||||
void peakSynthesisDoubleAxisY(const double,const double,const QString objectName);
|
||||
void peakSynthesisSingleAxisY(const double,const double,const QString objectName);
|
||||
private:
|
||||
AnalysisOperationRecorder::AnalysisMode _analysisMode;
|
||||
LocalCustomPlot *_customPlot;
|
||||
|
Loading…
Reference in New Issue
Block a user