microwave-project-unite/src/components/rtReport/index.vue

729 lines
28 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="rtReport">
<div class="realResult">
<div class="box1"><span class="sp1"></span><span class="sp2">真实性检验结果</span></div>
<div class="resContent">
<el-table
:header-cell-style="headerRowClass"
:cell-style="tableRowClassName"
style="width: 100%"
:data="tDatas"
:stripe="true"
class="table-head-transparent"
size="medium"
>
<el-table-column
v-for="(item, index) in Object.keys(tData).slice(0, midValue)"
:key="index"
:label="item | truthFunFilter"
:property="item"
align="center"
>
<template slot-scope="scope">{{ scope.row[item] }}</template>
</el-table-column>
</el-table>
<el-table
:header-cell-style="headerRowClass"
:cell-style="tableRowClassName"
style="width: 100%; margin-top: 16px"
:data="tDatas"
:stripe="true"
class="table-head-transparent"
size="medium"
>
<el-table-column
v-for="(item, index) in Object.keys(tData).slice(midValue)"
:key="index"
:label="item | truthFunFilter"
:property="item"
align="center"
>
<template slot-scope="scope">{{ scope.row[item] }}</template>
</el-table-column>
</el-table>
<!--<span v-for="(item,index) in resMap" :key="index">{{item.name | truthFunFilter}}{{item.val}}</span>-->
<div v-if="meanError.length !== 0 && meanError !== []">
<el-table
:header-cell-style="headerRowClass"
:cell-style="tableRowClassName"
style="width: 100%"
:data="meanError"
:stripe="true"
size="medium"
>
<el-table-column
prop="8_0"
label="平均相对误差相对X轴误差"
align="center"
v-if="meanError[0]['8_0'] != null"
>
</el-table-column>
<el-table-column
prop="8_1"
label="平均相对误差相对Y轴误差"
align="center"
v-if="meanError[0]['8_1'] != null"
>
</el-table-column>
<el-table-column
prop="24_0"
label="平均绝对相对误差相对X轴误差"
align="center"
v-if="meanError[0]['24_0'] != null"
>
</el-table-column>
<el-table-column
prop="24_1"
label="平均绝对相对误差相对Y轴误差"
align="center"
v-if="meanError[0]['24_1'] != null"
>
</el-table-column>
</el-table>
</div>
<!--<span>相对误差:</span>-->
<!-- <div v-if="relativeError.length !== 0 && relativeError !== []">
<el-table
:data="relativeError"
size="medium"
>
<el-table-column
prop="cre_orthoXRelativeError"
label="相对误差相对X轴误差"
align="center">
</el-table-column>
<el-table-column
prop="cre_orthoYRelativeError"
label="相对误差相对Y轴误差"
align="center">
</el-table-column>
</el-table>
</div> -->
</div>
</div>
<div class="errorGraph">
<div class="box1">
<span class="sp1"></span><span class="sp2">{{ pdSubTypeName }}误差结果图</span>
</div>
<div class="errContent">
<div id="rtReportEcharts" ref="chart"></div>
<div class="legend" v-if="pdSubType === 1">
<div class="line">
<span class="circle"></span>
<span>样本点</span>
</div>
<div class="line">
<span class="circle_2"></span>
<span>选取点</span>
</div>
</div>
<!-- <div class="erTip" v-else>
<div class="echartReg">
<span class="echartRegName"></span>
<span>{{ erExpression }}</span>
</div>
<div class="echartReg" v-show="erR2 !== null">
<span class="echartRegName"></span>
<span>{{ erR2 }}</span>
</div>
</div> -->
</div>
</div>
</div>
</template>
<script>
import { productTypeMap } from "@/lib/variateMap";
import { truthFunVal, productSubTypeVal } from "@/lib/contract";
import * as turf from "@turf/turf";
export default {
props: {
realRes: {
require: true,
},
pdSubType: {
require: true,
},
},
filters: {
truthFunFilter(truthFun) {
const truthFunMap = {
4: "平均误差",
9: "平均绝对误差",
5: "相对误差",
8: "平均相对误差",
24: "平均绝对相对误差",
6: "均方根误差",
23: "平面中误差",
7: "相关系数",
12: "误差矩阵",
14: "总体分类精度",
13: "Kappa系数",
};
return truthFunMap[truthFun];
},
},
data() {
return {
resMap: [],
myCharts: null,
relativeError: [],
meanError: [],
pdSubTypeName: "",
tData: {},
tDatas: null,
midValue: 10,
erExpression: null,
erR2: "0.037207",
};
},
created() {
this.initParam();
},
mounted() {
this.myCharts = this.$echarts.init(this.$refs.chart);
if (this.pdSubType === productSubTypeVal.ACS_ORTHOPHOTO) {
this.drawOtgEchart(this.realRes.otgVal);
let da = {};
let dae = {};
for (let i = 0; i < this.resMap.length; i++) {
const o = this.resMap[i];
if (typeof o.val === "number" || typeof o.val === "string") {
da[o.name] = o.val;
} else if (Number(o.name) === truthFunVal.ACM_MEANRELATIVEERROR) {
dae[o.name + "_0"] = o.val.X轴平均相对误差;
dae[o.name + "_1"] = o.val.Y轴平均相对误差;
} else if (Number(o.name) === truthFunVal.ACM_MEANABSOLUTERELATIVEERROR) {
dae[o.name + "_0"] = o.val.X轴平均相对绝对误差;
dae[o.name + "_1"] = o.val.Y轴平均相对绝对误差;
}
}
if (Object.keys(dae).length !== 0) {
this.meanError = [dae];
}
this.tData = da;
this.tDatas = [da];
} else {
this.drawPie(this.realRes.errorImageValue);
let da = {};
this.midValue =
this.resMap.length - 1 >= 3
? Math.ceil((this.resMap.length - 1) / 2)
: this.resMap.length;
for (let i = 0; i < this.resMap.length; i++) {
const o = this.resMap[i];
if (
Number(o.name) === truthFunVal.ACM_RELATIVEERROR ||
Number(o.name) === truthFunVal.ACM_REALVALLIST
)
continue; //跳过执行相对误差与真值列表
da[o.name] =
typeof o.val === "number" || typeof o.val === "string" ? o.val : o.val[0];
}
this.tDatas = [da];
this.tData = da;
}
},
methods: {
headerRowClass() {
return "background: #E4E9F1;text-align:center";
},
tableRowClassName({ rowIndex }) {
if ((rowIndex + 1) % 2 !== 0) {
return "background:#F5F7FA;text-align:center";
} else {
return "background:#FFFFFF;text-align:center";
}
},
getProductDes() {
let prodDes = null;
switch (this.pdSubType) {
case productSubTypeVal.ACS_DEM:
prodDes = "米";
break;
case productSubTypeVal.ACS_BACKSCATTERINGCOEFFICIENT:
prodDes = "dB";
break;
case productSubTypeVal.ACS_ATMOSPHERICDELAYCORRECTION:
prodDes = "米";
break;
case productSubTypeVal.ACS_DEFORMATION:
prodDes = "米";
break;
case productSubTypeVal.ACS_SOILMOISTURE:
prodDes = "立方厘米/立方厘米";
break;
case productSubTypeVal.ACS_SOILSALINITYINVERSION:
prodDes = "克/千克";
break;
case productSubTypeVal.ACS_SURFACEROUGHNESS:
prodDes = "厘米";
break;
case productSubTypeVal.ACS_GROUNDVEGETATIONHEIGHT:
prodDes = "单位:米";
break;
case productSubTypeVal.ACS_GROUNDLEAFAREAINDEX:
prodDes = "LAI值";
break;
}
return prodDes;
},
initParam() {
// console.log('报告信息',this.realRes)
if (this.realRes !== undefined) {
this.pdSubTypeName = productTypeMap(this.pdSubType);
const rr = this.realRes.report;
if (this.pdSubType === productSubTypeVal.ACS_ORTHOPHOTO) {
for (var i in rr) {
let rVal = rr[i];
switch (Number(i)) {
case truthFunVal.ACM_RELATIVEERROR: //相对误差
this.relativeError = rVal;
break;
case truthFunVal.ACM_MEANRELATIVEERROR: //平均相对误差
const objMap1 = {
cre_orthoXMeanRelativeError: "X轴平均相对误差",
cre_orthoYMeanRelativeError: "Y轴平均相对误差",
};
rVal = Object.fromEntries(
Object.entries(rVal).map(([k, v]) => [objMap1[k] || k, v])
);
this.resMap.push({ name: i, val: rVal });
break;
case truthFunVal.ACM_MEANABSOLUTERELATIVEERROR: //平均绝对相对误差
const objMap2 = {
cre_orthoXMeanAbsoluteRelativeError: "X轴平均相对绝对误差",
cre_orthoYMeanAbsoluteRelativeError: "Y轴平均相对绝对误差",
};
rVal = Object.fromEntries(
Object.entries(rVal).map(([k, v]) => [objMap2[k] || k, v])
);
this.resMap.push({ name: i, val: rVal });
break;
default:
this.resMap.push({ name: i, val: rVal });
}
}
} else {
for (var i in rr) {
let rVal = rr[i];
this.resMap.push({ name: i, val: rVal });
}
}
}
},
drawPie(errorVala) {
let data = [];
let xArr = [];
for (let i in errorVala) {
const a = [errorVala[i].cre_imageValue, errorVala[i].cre_deviation];
xArr.push(errorVala[i].cre_imageValue);
data.push(a);
}
// const x_limit = Math.abs(Math.max(...xArr) / xArr.length);
//多项式回归
let myRegression = this.echartRegression("polynomial", data, 1);
var option = {
title: {
text: this.pdSubTypeName + "误差结果图",
left: "center",
top: 16,
},
animation: false,
grid: {
right: "15%",
bottom: "25%",
},
toolbox: {
show: true,
orient: "vertical",
top: 10,
feature: {
dataZoom: {
title: {
zoom: "区域缩放",
back: "缩放还原",
},
yAxisIndex: "none",
},
myTool1: {
show: true,
title: "多项式回归1次",
icon: "path://M272.5,285.5h332m-171-137v296m89-224c-85.7,61.79-199.22,144.16-199,144",
onclick: () => {
myRegression = this.echartRegression("polynomial", data, 1);
option.series[1].data = myRegression.points;
this.myCharts.setOption(option);
},
},
myTool2: {
show: true,
title: "多项式回归2次",
icon: "path://M272.5,285.5h332m-171-137v296M338,219.21c5,112.41,55.28,190.63,93,192.37,38.46,1.77,90.59-74.67,91.71-192.82",
onclick: () => {
myRegression = this.echartRegression("polynomial", data, 2);
option.series[1].data = myRegression.points;
this.myCharts.setOption(option);
},
},
myTool3: {
show: true,
title: "多项式回归3次",
icon: "path://M272.5,285.5h332m-171-137v296M590,227c-24.25,54.05-59.27,114.65-98.35,113.21-51.58-1.9-71.15-110.45-119.35-110.68-21.39-.1-51.7,21.12-88.8,120",
onclick: () => {
myRegression = this.echartRegression("polynomial", data, 3);
option.series[1].data = myRegression.points;
this.myCharts.setOption(option);
},
},
restore: {
title: "还原",
icon: "path://M2.5 2v6h6M2.66 15.57a10 10 0 1 0 .57-8.38",
},
saveAsImage: {
title: "保存为图片",
},
},
},
dataZoom: [
{
type: "slider",
xAxisIndex: 0,
filterMode: "none",
},
{
type: "slider",
yAxisIndex: 0,
filterMode: "none",
right: "60",
},
],
legend: {
top: 20,
right: 45,
// selectedMode: false,
data: [
{
name: "erExpression",
icon: "circle",
},
// {
// name: "r2",
// icon: "circle",
// },
],
formatter: (name) => {
if (name === "erExpression") return this.erExpression;
else if (name === "r2") return this.erR2;
},
},
xAxis: {
name: "像元值(" + this.getProductDes() + "",
nameLocation: "middle",
// min: Number((Math.min(...xArr) - x_limit).toFixed(5)),
// max: Number((Math.max(...xArr) + x_limit).toFixed(5)),
nameTextStyle: {
lineHeight: 30,
height: 60,
// fontWeight: "bold",
fontSize: 13,
},
},
yAxis: {
name: "误差",
nameTextStyle: {
lineHeight: 30,
height: 60,
// fontWeight: "bold",
fontSize: 13,
padding: [0, 0, 10, 0],
},
nameRotate: 90, // 因为是在rightMiddle 所以需要其翻转 将其改为负值
nameLocation: "center", // y轴name处于y轴的什么位置
},
series: [
{
name: "r2",
symbolSize: 10,
type: "scatter",
data: data,
},
{
name: "erExpression",
type: "line",
smooth: true,
showSymbol: false,
data: myRegression.points,
// itemStyle: {
// normal: {
// color: "#91cc75",
// lineStyle: {
// width: 3,
// },
// },
// },
},
],
};
option && this.myCharts.setOption(option);
},
drawOtgEchart(otgVal) {
let xl = [];
let yl = [];
let allData = [];
let allData1 = [];
let allData2 = [];
for (let i in otgVal) {
xl.push(otgVal[i].x);
yl.push(otgVal[i].y);
let ad = [];
ad.push(otgVal[i].x, otgVal[i].y);
allData.push(ad);
const j = Number(i) + 1;
if (Number.isInteger(j / 2)) {
// allData.push("-");
}
}
allData.forEach((item, index) => {
if (index % 2 === 0) {
allData1.push(item);
} else {
allData2.push(item);
}
});
// 计算两点角度
let bearingArr = [];
allData1.forEach((item, index) => {
let point1 = turf.point(item);
let point2 = turf.point(allData2[index]);
let bearing = turf.rhumbBearing(point2, point1);
bearingArr.push(bearing);
});
let xMax = Math.max(...xl),
xMin = Math.min(...xl);
let yMax = Math.max(...yl),
yMin = Math.min(...yl);
const avgxVal = (xMax - xMin) / 8;
const avgyVal = (yMax - yMin) / 8;
let option = {
grid: {
left: "14%",
},
animation: false,
xAxis: {
name: "X",
nameLocation: "middle",
nameTextStyle: {
lineHeight: 30,
height: 60,
fontWeight: "bold",
},
min: Number(xMin - avgxVal * 2).toFixed(4),
max: Number(xMax + avgxVal * 2).toFixed(4),
axisLabel: {
formatter: function (value) {
let pt = turf.point([value, 0]);
let converted = turf.toMercator(pt);
let num = converted.geometry.coordinates[0];
const p = Math.floor(Math.log(num) / Math.LN10);
const n = num * 10 ** -p;
return `${n.toFixed(4)}xe${p}`;
},
},
},
yAxis: {
name: "Y",
nameTextStyle: {
lineHeight: 30,
height: 60,
fontWeight: "bold",
},
min: Number(yMin - avgyVal * 2).toFixed(4),
max: Number(yMax + avgyVal * 2).toFixed(4),
axisLabel: {
formatter: function (value) {
let pt = turf.point([0, value]);
let converted = turf.toMercator(pt);
let num = converted.geometry.coordinates[1];
const p = Math.floor(Math.log(num) / Math.LN10);
const n = num * 10 ** -p;
return `${n.toFixed(4)}xe${p}`;
},
},
},
series: [
// {
// symbolSize: 8,
// data: allData,
// type: "line",
// itemStyle: {
// color: function (params) {
// if ((params.dataIndex + 1) % 3 === 2) return "#0000CD";
// },
// },
// },
{
symbol: "circle",
type: "scatter",
itemStyle: {
// 填充颜色
color: "rgba(255, 0, 0, 0)",
// 边框颜色
borderColor: "rgba(0, 0, 0, 1)",
// 边框宽度
borderWidth: 2,
// 边框圆角
borderRadius: 5,
},
symbolSize: 15,
data: allData1,
},
{
// symbol: "image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAjVJREFUeF7tmM1JAwEYBb90Yg1WYGeWYhd69OTVEjxagldlJeAfibtkIBOYgARk8/ZlJm/jupseKgI7VZvKTEJkH4KEJERGQFanhSRERkBWp4UkREZAVqeFJERGQFanhSRERkBWp4UkREZAVqeFJERGQFanhSRERkBWp4UkREZAVqeFJERGQFanhSRERkBWp4UkREZAVqeFJERGQFanhSRERkBWp4UkREZAVqeFJERGQFanhSRERkBWp4UkREZAVqeFJERGQFanhSRERkBWp4UkREaAq3M9M8+nxrWQUwl+vf59Zl5m5mFm7vfPy+82PRKyCdfRg3/Df9tLWQQtP69rTpWQNZTWHfPfGp6+CTp4aVuE3M7MzbpzdtQRAlsYHry0LUIeE3LWD9qPS1tCzuri8+R/hNzNzNX5e118A+ySdfEkJG8A+1KXvJ+Lr9GfvTKF3RjKhPSvE5kQpE536ghGLiQhHEskKSEIRi4kIRxLJCkhCEYuJCEcSyQpIQhGLiQhHEskKSEIRi4kIRxLJCkhCEYuJCEcSyQpIQhGLiQhHEskKSEIRi4kIRxLJCkhCEYuJCEcSyQpIQhGLiQhHEskKSEIRi4kIRxLJCkhCEYuJCEcSyQpIQhGLiQhHEskKSEIRi4kIRxLJCkhCEYuJCEcSyQpIQhGLiQhHEskKSEIRi4kIRxLJCkhCEYuJCEcSyQpIQhGLiQhHEskKSEIRi4kIRxLJCkhCEYuJCEcSyQpIQhGLuQDLNIwmfEn5ZUAAAAASUVORK5CYII=",
symbol: "image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAYAAAA4TnrqAAAAv0lEQVR4nO3UsUmEQRCA0U801cASxECwAUOrMLEly7CGM7OAM/ZSCxBzA0ERLjqQQ3G5X//3YLPdYWZ2dgMAAAAAAAAAAIBd25/hDVxUR9Xzdw/OsVmn1bK6qk6qt+ppAnlN0mX1vrFeqtvqujr+Kum9CRe1HBT3sDrbsue+WlR31WpQHr9q8/Z3tR6rm8/CDibcrIdBcf/lZI3y4z9rypM12mo9OYv1JG01x2a9Vudzf14AAAAAAAAAAAD8RdUHTdhBNENzGoYAAAAASUVORK5CYII=",
symbolRotate: (number, params) => {
console.log(number, params);
return bearingArr[params.dataIndex];
},
// symbolOffset: ["20%", "-5%"],
type: "scatter",
symbolSize: 60,
data: allData1,
},
],
};
option && this.myCharts.setOption(option);
},
echartRegression(regressionType, data, order) {
//regressionType:回归类型'linear', 'exponential', 'logarithmic', 'polynomial'order:多项式的阶数number。对于非多项式回归可以忽略该参数。
let myRegression = this.$ecstat.regression(regressionType, data, order);
myRegression.points.sort(function (a, b) {
return a[0] - b[0];
});
this.erExpression = myRegression.expression;
return myRegression;
},
},
};
</script>
<style scoped lang="less">
.rtReport {
width: 100%;
height: 100%;
}
.realResult {
width: 100%;
height: calc(55% - 5px);
background-color: white;
margin-bottom: 5px;
}
.errorGraph {
width: 100%;
height: 45%;
background-color: white;
}
.resContent {
border: 1px black solid;
height: calc(100% - 60px);
width: calc(100% - 20px);
margin: 10px;
font-size: 20px;
overflow-y: scroll;
span {
display: block;
margin: 10px;
}
}
.errContent {
border: 1px black solid;
height: calc(100% - 60px);
width: calc(100% - 20px);
margin: 10px;
position: relative;
}
#rtReportEcharts {
width: 100%;
height: 100%;
position: relative;
}
.box1 {
height: 40px;
line-height: 40px;
border-bottom: 1px solid rgb(205, 205, 205, 0.5);
}
.sp1 {
display: inline-block;
width: 7px;
height: 26px;
background-color: #354595;
vertical-align: top;
margin-left: 20px;
margin-top: 8px;
}
.sp2 {
margin-left: 10px;
font-size: 20px;
font-weight: 700;
color: #354595;
vertical-align: top;
}
.legend {
position: absolute;
top: 20px;
right: 20px;
background-color: transparent;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
.line {
height: 20px;
line-height: 20px;
margin: 0 5px;
.circle {
display: inline-block;
width: 7px;
height: 7px;
border: 1px solid rgb(194, 53, 49);
border-radius: 50%;
margin-right: 5px;
}
.circle_2 {
display: inline-block;
width: 7px;
height: 7px;
border-radius: 50%;
margin-right: 5px;
border: 1px solid #0000cd;
}
}
}
.erTip {
position: absolute;
top: 10px;
right: 26px;
font-size: small;
text-align: end;
.echartReg {
height: 20px;
line-height: 20px;
margin: 0 5px;
.echartRegName {
display: inline-block;
width: 9px;
height: 9px;
background-color: #7a96c6;
// border: 1px solid #7A96C6;
border-radius: 50%;
margin-right: 5px;
}
}
}
</style>