6.95
This commit is contained in:
@ -8,6 +8,11 @@ pub fn interpolate_spline(x: Vec<f64>, y: Vec<f64>, step: f64) ->Vec<(f64, f64)>
|
||||
spectraltools::interpolate_spline(x, y, step).unwrap()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn interpolate_spline_smooth(x: Vec<f64>, y: Vec<f64>, step: f64) ->Vec<(f64, f64)>{
|
||||
spectraltools::interpolate_spline_smooth(x, y, step).unwrap()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn interpolate_spline_at_points(x: Vec<f64>, y: Vec<f64>, x_target: Vec<f64>) -> Vec<f64>{
|
||||
spectraltools::interpolate_spline_at_points(x, y, x_target).unwrap()
|
||||
|
||||
@ -39,6 +39,40 @@ pub fn interpolate_spline<T: Copy + Into<f64>,>(x_t: Vec<T>, y_t: Vec<T>, step:
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn interpolate_spline_smooth<T: Copy + Into<f64>>(x_t: Vec<T>, y_t: Vec<T>, step: f64) -> Result<Vec<(f64, f64)>, Box<dyn Error>> {
|
||||
let x: Vec<f64> = x_t.iter().map(|&x| x.into()).collect();
|
||||
let y: Vec<f64> = y_t.iter().map(|&y| y.into()).collect();
|
||||
|
||||
if x.len() != y.len() {
|
||||
return Err("x and y must have the same length".into());
|
||||
}
|
||||
|
||||
// 使用 Catmull-Rom 样条插值(平滑曲线)
|
||||
let keys: Vec<Key<f64, f64>> = x.iter()
|
||||
.zip(y.iter())
|
||||
.map(|(&x, &y)| Key::new(x, y, Interpolation::CatmullRom))
|
||||
.collect();
|
||||
|
||||
let spline = Spline::from_vec(keys);
|
||||
|
||||
// 计算 x 的最大值和最小值
|
||||
let &start = x.iter().min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
|
||||
let &end = x.iter().max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
|
||||
|
||||
// 插值到间隔为 step 的点
|
||||
let mut result = Vec::new();
|
||||
let mut t = start;
|
||||
|
||||
while t <= end {
|
||||
if let Some(value) = spline.clamped_sample(t) {
|
||||
result.push((t, value));
|
||||
}
|
||||
t += step;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn interpolate_spline_at_points<T: Copy + Into<f64>>(x_t: Vec<T>, y_t: Vec<T>, x_target: Vec<f64>) -> Result<Vec<f64>, Box<dyn Error>> {
|
||||
let x: Vec<f64> = x_t.iter().map(|&x| x.into()).collect();
|
||||
let y: Vec<f64> = y_t.iter().map(|&y| y.into()).collect();
|
||||
@ -181,4 +215,42 @@ fn test_find_peek(){
|
||||
for p in peaks {
|
||||
println!("{} {}", p.0, p.1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compute_weave_coeff_with_data(){
|
||||
let pixels = vec![79.0, 128.0, 146.0, 157.0, 201.0, 240.0, 261.0, 334.0, 362.0, 436.0];
|
||||
let wavelengths = vec![965.779, 892.869, 866.794, 850.887, 785.482, 727.294, 696.543, 587.092, 546.074, 435.833];
|
||||
|
||||
let result = compute_weave_coeff(pixels.clone(), wavelengths.clone());
|
||||
|
||||
let a0 = result[3]; // 三次项
|
||||
let a1 = result[2]; // 二次项
|
||||
let a2 = result[1]; // 一次项
|
||||
let a3 = result[0]; // 常数项
|
||||
|
||||
println!("=== compute_weave_coeff 原始返回 ===");
|
||||
println!("[{:.15e}, {:.15e}, {:.15e}, {:.15e}]", result[0], result[1], result[2], result[3]);
|
||||
|
||||
println!();
|
||||
println!("=== 前端 bochangxishu ===");
|
||||
println!("a0 (³项) = {:.15e}", a0);
|
||||
println!("a1 (²项) = {:.15e}", a1);
|
||||
println!("a2 (¹项) = {:.15e}", a2);
|
||||
println!("a3 (常数) = {:.15e}", a3);
|
||||
|
||||
println!();
|
||||
println!("=== 拟合验证 ===");
|
||||
for i in 0..pixels.len() {
|
||||
let p = pixels[i];
|
||||
let pred = result[0] + result[1]*p + result[2]*p.powi(2) + result[3]*p.powi(3);
|
||||
println!("像素 {:3.0}: 输入={:.3}nm, 拟合={:.3}nm, 误差={:+.3}nm", p, wavelengths[i], pred, pred-wavelengths[i]);
|
||||
}
|
||||
|
||||
println!();
|
||||
println!("=== 前端公式: weave = a0*p³ + a1*p² + a2*p + a3 ===");
|
||||
for &p in &[0.0_f64, 79.0, 128.0, 146.0, 157.0, 201.0, 240.0, 261.0, 334.0, 362.0, 436.0, 2047.0] {
|
||||
let pred = a0*p.powi(3) + a1*p.powi(2) + a2*p + a3;
|
||||
println!("像素 {:4.0}: {:.3}nm", p, pred);
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@ mod comman1;
|
||||
mod myformatiris;
|
||||
use comman1::*;
|
||||
use algorithm::interpolate_spline;
|
||||
use algorithm::interpolate_spline_smooth;
|
||||
use algorithm::sg_smooth;
|
||||
use mydefine::*;
|
||||
use iris_spectral::spectralbase::Senortype;
|
||||
@ -245,6 +246,7 @@ fn main() {
|
||||
readformport,
|
||||
sendtoport,
|
||||
interpolate_spline,
|
||||
interpolate_spline_smooth,
|
||||
sg_smooth,
|
||||
savecalibratefile,
|
||||
savecalibratefileIRIS,
|
||||
|
||||
@ -463,6 +463,7 @@ export default {
|
||||
let coeffweave3 = this.Devinfo.bochangxishu.a2;
|
||||
let coeffweave4 = this.Devinfo.bochangxishu.a3;
|
||||
await SensorMethod.Set_Gain(this.sensor_gain_up);
|
||||
await SensorMethod.Get_Dark_Data(dire, this.shutter_time_up, Number(this.caijicishu[0]));
|
||||
var data = await SensorMethod.Get_Date_on_Derction(dire, this.shutter_time_up, true, Number(this.caijicishu[0]))
|
||||
let lastvalue = this.DataUP.value_lable;
|
||||
this.DataUP = data;
|
||||
@ -487,6 +488,7 @@ export default {
|
||||
let coeffweave3 = this.Devinfo.bochangxishu2.a2;
|
||||
let coeffweave4 = this.Devinfo.bochangxishu2.a3;
|
||||
await SensorMethod.Set_Gain(this.sensor_gain_down);
|
||||
await SensorMethod.Get_Dark_Data(dire, this.shutter_time_up, Number(this.caijicishu[0]));
|
||||
var data = await SensorMethod.Get_Date_on_Derction(dire, this.shutter_time_down, true, Number(this.caijicishu[1]))
|
||||
let lastvalue = this.DataDown.value_lable;
|
||||
this.DataDown = data;
|
||||
|
||||
@ -274,7 +274,7 @@ export default {
|
||||
if (specindex == 0) {
|
||||
let originalData = this.Data.data;
|
||||
// Step 1: 亚像素插值 (0.05像素间隔,20倍数据量)
|
||||
let resampled = await invoke("interpolate_spline", {
|
||||
let resampled = await invoke("interpolate_spline_smooth", {
|
||||
x: Array.from({length: originalData.length}, (_, i) => i),
|
||||
y: originalData.map(v => Number(v)),
|
||||
step: 0.05
|
||||
@ -349,7 +349,7 @@ export default {
|
||||
else if (specindex == 1) {
|
||||
let originalDataDown = this.DataDown.data;
|
||||
// Step 1: 亚像素插值 (0.05像素间隔,20倍数据量)
|
||||
let resampledDown = await invoke("interpolate_spline", {
|
||||
let resampledDown = await invoke("interpolate_spline_smooth", {
|
||||
x: Array.from({length: originalDataDown.length}, (_, i) => i),
|
||||
y: originalDataDown.map(v => Number(v)),
|
||||
step: 0.05
|
||||
@ -605,6 +605,8 @@ export default {
|
||||
var chart_up = echarts.getInstanceByDom(this.$refs.chart_weavelenth);
|
||||
chart_up.setOption(this.option);
|
||||
|
||||
await this.savePeakResultToCSV(0, orgdata);
|
||||
|
||||
} else if (spectralnumber == 1) {
|
||||
this.Devinfo.bochangxishu2.a0 = result[3];
|
||||
this.Devinfo.bochangxishu2.a1 = result[2];
|
||||
@ -626,6 +628,8 @@ export default {
|
||||
var chart_up = echarts.getInstanceByDom(this.$refs.chart_weavelenth_down);
|
||||
chart_up.setOption(this.optiondown);
|
||||
|
||||
await this.savePeakResultToCSV(1, orgdata);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
@ -670,7 +674,55 @@ export default {
|
||||
|
||||
await fs.writeTextFile(savePath, JSON.stringify(data, null, 2));
|
||||
},
|
||||
|
||||
async savePeakResultToCSV(spectralnumber, orgdata) {
|
||||
if (!orgdata || orgdata.length === 0) return;
|
||||
|
||||
const now = new Date();
|
||||
const pad = n => String(n).padStart(2, '0');
|
||||
const dateStr = `${now.getFullYear()}${pad(now.getMonth()+1)}${pad(now.getDate())}_${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
|
||||
const serial = this.Devinfo?.serialnumber || this.Devinfo?.SerilNumber || "Unknown";
|
||||
const isDual = this.Devinfo?.fiber_type === "Dual";
|
||||
const sensorLabel = spectralnumber === 0 ? "UP" : "DOWN";
|
||||
|
||||
let fileSuffix = "";
|
||||
if (isDual) {
|
||||
fileSuffix = `_${sensorLabel}`;
|
||||
}
|
||||
const defaultName = `${serial}${fileSuffix}_${dateStr}.csv`;
|
||||
|
||||
const savePath = await dialog.save({
|
||||
defaultPath: defaultName,
|
||||
filters: [{ name: "CSV文件", extensions: ["csv"] }]
|
||||
});
|
||||
if (!savePath) return;
|
||||
|
||||
const coeff = spectralnumber === 0
|
||||
? [this.Devinfo.bochangxishu.a0, this.Devinfo.bochangxishu.a1, this.Devinfo.bochangxishu.a2, this.Devinfo.bochangxishu.a3]
|
||||
: [this.Devinfo.bochangxishu2.a0, this.Devinfo.bochangxishu2.a1, this.Devinfo.bochangxishu2.a2, this.Devinfo.bochangxishu2.a3];
|
||||
|
||||
let lines = [];
|
||||
lines.push(`# 设备序号: ${serial}`);
|
||||
lines.push(`# 传感器: ${sensorLabel}`);
|
||||
lines.push(`# 时间: ${now.toISOString()}`);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
lines.push(`# a${i}: ${coeff[i]}`);
|
||||
}
|
||||
lines.push("像素,参考波长,拟合波长,误差");
|
||||
|
||||
orgdata.forEach(el => {
|
||||
if (el[3] === true) {
|
||||
let pix = el[2];
|
||||
let refWl = el[4];
|
||||
let fitWl = coeff[0]*pix*pix*pix + coeff[1]*pix*pix + coeff[2]*pix + coeff[3];
|
||||
let err = fitWl - refWl;
|
||||
let errStr = err >= 0 ? "+" + err.toFixed(3) : err.toFixed(3);
|
||||
lines.push(`${pix},${refWl},${fitWl.toFixed(3)},${errStr}`);
|
||||
}
|
||||
});
|
||||
|
||||
await fs.writeTextFile(savePath, lines.join("\n"));
|
||||
},
|
||||
|
||||
/**
|
||||
* 光谱峰自动匹配函数
|
||||
* @param {number[]} detectedPeaks - 检测到的峰位置数组(单位:像素或通道号)
|
||||
|
||||
Reference in New Issue
Block a user