//输入参考波长和寻峰范围,输出该范围内峰顶对应的波长和光强 public double[] findWaveSpec_Range(spec_metadata spec_data, double wave_example, double range) { double[] re = new double[2]; double begin = wave_example - range / 2; double end = wave_example + range / 2; re[0] = -1; re[1] = -1; for (int i = 0; i < spec_data.read_wave_all.Length; i++) { if ((begin <= spec_data.read_wave_all[i]) && (spec_data.read_wave_all[i] <= end)) { if (spec_data.read_spec_all_now[i] > re[1]) { re[0] = spec_data.read_wave_all[i]; re[1] = spec_data.read_spec_all_now[i]; } } else { continue; } } return(re); }
//获取某元素波长的方程,前置约束为调用者已经完成所有所有标样的读取 //函数返回方程的同时,将返回方程进行计算时用到的标样点 public static LinearFit.LfReValue get_equation(spec_metadata spec_obj, int element_index, ref double[] concentration, ref double[] standards_integration_average_strenth, int bs) { double[] wave_all = spec_obj.read_wave_all; double[] env = spec_obj.env_spec; standard[] standards = spec_obj.standards; int standard_cnt = spec_obj.standard_cnt; select_element element = spec_obj.elements[element_index]; double[,,] spec_standard = spec_obj.read_standard_spec; //提取该元素列标样数据,得到方程 standards_integration_average_strenth = new double[standard_cnt]; //标样平均的积分平均强度 for (int i = 0; i < standard_cnt; i++) //每个标样 { double standard_element_interval_average = 0.0; //平均的平均 //如果点击的为标样,在计算方程的循环中直接获取多次积分平均值 double[] strenght_oneshot = get_oneshot_all_strength(spec_obj, i, element_index); for (int t = 0; t < standards[i].average_times; t++) { standard_element_interval_average += strenght_oneshot[t]; } standards_integration_average_strenth[i] = standard_element_interval_average / standards[i].average_times; } concentration = new double[standard_cnt]; //浓度 for (int j = 0; j < standard_cnt; j++) { concentration[j] = standards[j].standard_ppm[element.sequece_index - 1]; } LinearFit.LfReValue equation; //过空白或不过空白读取 if (bs == 0) { equation = LinearFit.linearFitFunc(concentration, standards_integration_average_strenth, standard_cnt); } else { equation = LinearFit.linearFitFunc_blank(concentration, standards_integration_average_strenth, standard_cnt); } return(equation); }
//获取该cell对应的多次平均强度,index为标样或样本序号 public static double[] get_oneshot_all_strength(spec_metadata spec_obj, int rowindex, int element_index) { int this_read_average_times = 1; int standard_cnt = spec_obj.standard_cnt; double[,,] src_spec = null; int index = 0; double[] wave_all = spec_obj.read_wave_all; double[] env = spec_obj.env_spec; standard[] standards = spec_obj.standards; sample[] samples = spec_obj.samples; double interval_start = spec_obj.elements[element_index].interval_start; double interval_end = spec_obj.elements[element_index].interval_end; int pixel_cnt = spec_obj.read_wave_all.Length; if (rowindex < standard_cnt) //标样 { this_read_average_times = standards[rowindex].average_times; src_spec = spec_obj.read_standard_spec; index = rowindex; } else { this_read_average_times = samples[rowindex - standard_cnt].average_times; src_spec = spec_obj.read_sample_spec; index = rowindex - standard_cnt; } double[] strenght_oneshot = new double[this_read_average_times]; double[] spec_temp_all = new double[pixel_cnt]; for (int t = 0; t < this_read_average_times; t++) { for (int k = 0; k < pixel_cnt; k++) { spec_temp_all[k] = src_spec[index, t, k]; } strenght_oneshot[t] = data_util.get_integration_average(wave_all, spec_temp_all, env, interval_start, interval_end); } return(strenght_oneshot); }
//准备分析窗体峰视图显示的x_minimal,x_maximal,x_unit,y_minimal,y_maiximal,y_unit以及数据spec_selected private static void prepare_peak_chart_data(spec_metadata spec_obj, int click_row, int click_column, ref double[] spec_selected, ref double x_minimal, ref double x_maximal, ref double x_show_unit, ref double y_minimal, ref double y_maximal, ref int y_show_unit) { standard[] standards = spec_obj.standards; int standard_cnt = spec_obj.standard_cnt; double[,,] spec_standard = spec_obj.read_standard_spec; double[,,] spec_sample = spec_obj.read_sample_spec; double[] wave_all = spec_obj.read_wave_all; double[] env = spec_obj.env_spec; select_element element = spec_obj.elements[click_column - 3]; int pixel_cnt = spec_obj.read_wave_all.Length; spec_selected = new double[pixel_cnt]; if (click_row < standard_cnt) { for (int i = 0; i < pixel_cnt; i++) { spec_selected[i] = spec_standard[click_row, 0, i]; //展示波峰图时,简单的展示第0次平均的值 } } else { for (int i = 0; i < pixel_cnt; i++) { spec_selected[i] = spec_sample[click_row - standard_cnt, 0, i]; //展示波峰图时,简单的展示第0次平均的值 } } //设置显示配置 double peak_wave = element.peak_wave; x_minimal = peak_wave - 0.25; x_maximal = peak_wave + 0.25; int show_x_start = data_util.get_index_by_wave(wave_all, x_minimal); int show_x_end = data_util.get_index_by_wave(wave_all, x_maximal); y_minimal = spec_selected[show_x_start]; y_maximal = spec_selected[show_x_start]; for (int i = show_x_start; i < show_x_end; i++) { if (spec_selected[i] < y_minimal) { y_minimal = spec_selected[i]; } if (spec_selected[i] > y_maximal) { y_maximal = spec_selected[i]; } if (env[i] < y_minimal) { y_minimal = env[i]; } if (env[i] > y_maximal) { y_maximal = env[i]; } } y_maximal += (y_maximal - y_minimal) * 0.1; // maximal + 10% * range x_show_unit = 0.05; y_show_unit = data_util.normalize_y(y_minimal, y_maximal); //y的显示不随放大缩小改变, x将利用 data_util 来规范显示数据,初始时,x_show_unit固定为0.05 y_minimal = (int)((y_minimal - 0.001) / y_show_unit - 1) * y_show_unit; y_maximal = (int)((y_maximal - 0.001) / y_show_unit + 1) * y_show_unit; data_util.normalize_data_for_show(x_show_unit, 10, ref x_show_unit, ref x_minimal, ref x_maximal); // }
public static int process_cell_click(Chart chart1, Chart chart2, Label label2, Label label_info, DataGridView dataGridView9, int click_row, int click_column, spec_metadata spec_obj, int bs) { select_element[] elements = spec_obj.elements; standard[] standards = spec_obj.standards; sample[] samples = spec_obj.samples; double[] wave_all = spec_obj.read_wave_all; double[] env = spec_obj.env_spec; double[,,] spec_standard = spec_obj.read_standard_spec; double[,,] spec_sample = spec_obj.read_sample_spec; int standard_cnt = spec_obj.standard_cnt; int pixel_cnt = spec_obj.read_wave_all.Length; //判断该标样/样本是否读取 //绘制波峰图 //完成全部标样读取 //计算方程,绘制拟合方程图 //推算浓度,计算标准差 if (click_row < standard_cnt && standards[click_row].is_readed || click_row >= standard_cnt && samples[click_row - standard_cnt].is_read) { //绘制波峰图,设置显示配置 //chart_select_integral_interval.draw_chart(chart1,) double[] spec_selected = new double[pixel_cnt]; double peak_wave = elements[click_column - 3].peak_wave; double x_minimal = 0, x_maximal = 0, y_minimal = 0, y_maximal = 0, x_show_unit = 0; int y_show_unit = 0; prepare_peak_chart_data(spec_obj, click_row, click_column, ref spec_selected, ref x_minimal, ref x_maximal, ref x_show_unit, ref y_minimal, ref y_maximal, ref y_show_unit); double interval_start_wave = elements[click_column - 3].interval_start; double interval_end_wave = elements[click_column - 3].interval_end; bool is_standard = false; if (click_row < standard_cnt) { is_standard = true; } chart_select_integral_interval.draw_chart(chart1, x_show_unit, y_show_unit, x_minimal, x_maximal, y_minimal, y_maximal, peak_wave, interval_start_wave, interval_end_wave, wave_all, spec_selected, env, is_standard); } else { MessageBox.Show("需要先完成读取"); return(0); } for (int i = 0; i < standard_cnt; i++) { if (!standards[i].is_readed) { MessageBox.Show("需要所有标样完成读取才能计算方程"); return(0); } } //记录样本的多次读取数据 double[] this_read_integration_strenths = null; int this_read_average_times = 0; //用于计算方程的浓度和强度 double [] element_concentrations = null; double [] element_average_strenths = null; //bs为 LinearFit.LfReValue equation = get_equation(spec_obj, click_column - 3, ref element_concentrations, ref element_average_strenths, bs); this_read_integration_strenths = get_oneshot_all_strength(spec_obj, click_row, click_column - 3); this_read_average_times = this_read_integration_strenths.Length; double[] this_read_integration_concentrations = new double[this_read_average_times]; double this_read_strenth_average = 0, this_read_concentration_average = 0; for (int i = 0; i < this_read_average_times; i++) { this_read_integration_concentrations[i] = (this_read_integration_strenths[i] - equation.getA()) / equation.getB(); } for (int i = 0; i < this_read_average_times; i++) { this_read_strenth_average += this_read_integration_strenths[i]; } this_read_strenth_average /= this_read_average_times; this_read_concentration_average = (this_read_strenth_average - equation.getA()) / equation.getB(); equation_chart.draw_equation(chart2, label2, element_concentrations, element_average_strenths, equation.getA(), equation.getB(), equation.getR()); if (click_row < standard_cnt) { equation_chart.add_point_now(chart2, element_concentrations[click_row], element_average_strenths[click_row], Color.Red, MarkerStyle.Circle); } else { equation_chart.add_point_now(chart2, this_read_concentration_average, this_read_strenth_average, Color.Green, MarkerStyle.Triangle); } datagrid_control.draw_datagrid_snapshot(dataGridView9, this_read_integration_concentrations, this_read_integration_strenths); summary_info.draw_summary_info(label_info, this_read_concentration_average, this_read_strenth_average, this_read_integration_strenths, this_read_integration_concentrations); return(1); }
public static void read_spec_click(NumericUpDown textbox_average_times, spec_wrapper wrapper, DataGridView dgv, int row_index, spec_metadata spec_obj, int bs) { select_element[] elements = spec_obj.elements; standard[] standards = spec_obj.standards; sample[] samples = spec_obj.samples; double[] wave_all = spec_obj.read_wave_all; double[] env = spec_obj.env_spec; double[,,] spec_standard = spec_obj.read_standard_spec; double[,,] spec_sample = spec_obj.read_sample_spec; int standard_cnt = spec_obj.standard_cnt; int sample_cnt = spec_obj.sample_cnt; int element_cnt = spec_obj.element_cnt; double[] spec_now = null; int this_read_average_times = int.Parse(textbox_average_times.Text); if (this_read_average_times < 1 || this_read_average_times > 5) { this_read_average_times = 1; } //读标样 if (row_index < standard_cnt) { standards[row_index].average_times = this_read_average_times; for (int i = 0; i < standards[row_index].average_times; i++) { //从设备获取数据 spec_now = wrapper.get_spec_all(); for (int j = 0; j < spec_now.Length; j++) //赋值进数组 { spec_standard[row_index, i, j] = spec_now[j]; } } //设置已经读取,设置标样对象;通过标样确定样本读取峰,初始积分区间 for (int j = 0; j < element_cnt; j++) { //寻峰,确定实际读取波长,默认积分区间 int seek_start_index = data_util.get_index_by_wave(wave_all, elements[j].select_wave - elements[j].seek_peak_range / 2); int seek_end_index = data_util.get_index_by_wave(wave_all, elements[j].select_wave + elements[j].seek_peak_range / 2); int peak_index = data_util.find_peak(spec_now, seek_start_index, seek_end_index); elements[j].peak_wave = wave_all[peak_index]; elements[j].interval_start = elements[j].peak_wave - 0.05; //设置默认积分范围为峰左右0.25nm elements[j].interval_end = elements[j].peak_wave + 0.05; } standards[row_index].is_readed = true; } //读样本 if (row_index >= standard_cnt) { int sample_index = row_index - standard_cnt; samples[sample_index].average_times = this_read_average_times; for (int i = 0; i < samples[sample_index].average_times; i++) { //从设备获取数据 spec_now = wrapper.get_spec_all(); for (int j = 0; j < spec_now.Length; j++) //赋值进数组 { spec_sample[sample_index, i, j] = spec_now[j]; } } samples[sample_index].is_read = true; } //更新datagrid double[,] standards_val = new double[standard_cnt, element_cnt]; double[,] samples_val = new double[sample_cnt, element_cnt]; //预计算表格数据,统一调用datagrid_control来控制绘制,调用直接根据规则预先进行计算 datagrid_control.draw_datagrid_analysis(dgv, spec_obj, bs); }
public static void draw_datagrid_standard_setting(DataGridView dgv, select_element[] elements, standard[] standards, int element_cnt, int standard_cnt, spec_metadata spec_data) { //设置列 DataTable dtData = new DataTable(); dtData.Columns.Add("序号"); //dtData.Columns.Add("标签"); dtData.Columns.Add("标签"); for (int i = 0; i < element_cnt; i++) { dtData.Columns.Add(elements[i].element + "(" + elements[i].select_wave.ToString() + ")"); } //设置行 DataRow drData; //string concentration_unit = "ppm"; //这个可以放在标样对不同元素的浓度单位中 drData = dtData.NewRow(); drData[0] = ""; drData[1] = ""; for (int i = 0; i < element_cnt; i++) { if (spec_data.elements[i].danwei == 1) { drData[2 + i] = "ppm"; } else if (spec_data.elements[i].danwei == 2) { drData[2 + i] = "ppb"; } else if (spec_data.elements[i].danwei == 3) { drData[2 + i] = "%"; } } dtData.Rows.Add(drData); for (int l = 0; l < standard_cnt; l++) { drData = dtData.NewRow(); drData[0] = standards[l].standard_index + 1; //序号 drData[1] = standards[l].standard_label; for (int i = 0; i < element_cnt; i++) { /* * 1 ppm = 1000 ppb * 10000 ppm = 1 % */ if (spec_data.elements[i].danwei == 1) { drData[2 + i] = Math.Round(standards[l].standard_ppm[i], 7); } else if (spec_data.elements[i].danwei == 2) { //drData[2 + i] = Math.Round(standards[l].standard_ppm[i], 5); drData[2 + i] = Math.Round(standards[l].standard_ppm[i] * 1000, 7); } else if (spec_data.elements[i].danwei == 3) { drData[2 + i] = (decimal)Math.Round(standards[l].standard_ppm[i] / 10000, 7); } } dtData.Rows.Add(drData); } dgv.DataSource = dtData; }
public static bool is_datagrid_analysis_exist = false; //根据这个标识判断是否需要new新表格还是重用旧表格 //这部分只负责根据数据绘图,standard_val/sample_val为强度或者浓度 public static void draw_datagrid_analysis(DataGridView dgv, spec_metadata spec_obj, int bs) { select_element[] elements = spec_obj.elements; standard[] standards = spec_obj.standards; sample[] samples = spec_obj.samples; int standard_cnt = spec_obj.standard_cnt; int sample_cnt = spec_obj.sample_cnt; int element_cnt = spec_obj.element_cnt; double[,] standard_val = new double[standard_cnt, element_cnt]; double[,] sample_val = new double[sample_cnt, element_cnt]; fill_datagrid_data(spec_obj, ref standard_val, ref sample_val, bs); //列 DataTable dt8 = new DataTable(); dt8.Columns.Add("序号", typeof(string)); dt8.Columns.Add("溶液标签", typeof(string)); dt8.Columns.Add("读取状态", typeof(string)); for (int i = 0; i < element_cnt; i++) { dt8.Columns.Add(elements[i].element + "(" + elements[i].select_wave + ")", typeof(string)); } //行1 标准样本的数据显示 for (int i = 0; i < standard_cnt; i++) { DataRow dr8 = dt8.NewRow(); dr8[0] = (i + 1).ToString(); dr8[1] = standards[i].standard_label; if (standards[i].is_readed) { dr8[2] = "已读取"; } else { dr8[2] = "未读取"; } for (int j = 0; j < element_cnt; j++) { if (elements[j].danwei == 1) { dr8[j + 3] = Math.Round(standard_val[i, j], 7); } else if (elements[j].danwei == 2) { dr8[j + 3] = Math.Round(standard_val[i, j] * 1000, 7); } else if (elements[j].danwei == 3) { dr8[j + 3] = (decimal)Math.Round(standard_val[i, j] / 10000, 7); } } dt8.Rows.Add(dr8); } //行2 样本数据的显示 for (int i = 0; i < sample_cnt; i++) { DataRow dr8 = dt8.NewRow(); dr8[0] = (standard_cnt + 1 + i).ToString(); dr8[1] = samples[i].sample_label; if (samples[i].is_read) { dr8[2] = "已读取"; } else { dr8[2] = "未读取"; } for (int j = 0; j < element_cnt; j++) { if (elements[j].danwei == 1) { dr8[j + 3] = Math.Round(sample_val[i, j], 7); } else if (elements[j].danwei == 2) { dr8[j + 3] = Math.Round(sample_val[i, j], 5); } else if (elements[j].danwei == 3) { dr8[j + 3] = Math.Round(sample_val[i, j], 2); } } dt8.Rows.Add(dr8); } dgv.DataSource = dt8; for (int i = 0; i < standard_cnt; i++) { if (standards[i].is_readed) { dgv.Rows[i].Cells[2].Style.ForeColor = Color.Blue; } else { dgv.Rows[i].Cells[2].Style.ForeColor = Color.Gray; } } for (int i = 0; i < sample_cnt; i++) { if (samples[i].is_read) { dgv.Rows[i + standard_cnt].Cells[2].Style.ForeColor = Color.Blue; } else { dgv.Rows[i + standard_cnt].Cells[2].Style.ForeColor = Color.Gray; } } }
//根据实际测量数据spec_standard和spec_sample,选择的各元素,标样,样本,计算出将要显示的表格数据 //返回值standard_val和sample_val分别为计算后表格要显示的标样/样本的浓度或强度数据 private static void fill_datagrid_data(spec_metadata spec_obj, ref double[,] standard_val, ref double[,] sample_val, int bs) { select_element[] elements = spec_obj.elements; standard[] standards = spec_obj.standards; sample[] samples = spec_obj.samples; double[] wave_all = spec_obj.read_wave_all; double[] env = spec_obj.env_spec; double[,,] spec_standard = spec_obj.read_standard_spec; double[,,] spec_sample = spec_obj.read_sample_spec; int standard_cnt = spec_obj.standard_cnt; int sample_cnt = spec_obj.sample_cnt; int element_cnt = spec_obj.element_cnt; int pixel_cnt = spec_obj.read_wave_all.Length; double[,] standards_integration_average_strenth = new double[standard_cnt, element_cnt]; double[,] samples_integration_average_strenth = new double[sample_cnt, element_cnt]; //标样平均的积分平均强度 for (int i = 0; i < standard_cnt; i++) //每个标样 { if (!standards[i].is_readed) { continue; } for (int t = 0; t < standards[i].average_times; t++) { double[] spec_temp_all = new double[pixel_cnt]; for (int k = 0; k < pixel_cnt; k++) { spec_temp_all[k] = spec_standard[i, t, k]; } for (int j = 0; j < element_cnt; j++) //每一个元素 { standards_integration_average_strenth[i, j] += data_util.get_integration_average(wave_all, spec_temp_all, env, elements[j].interval_start, elements[j].interval_end); } } for (int j = 0; j < element_cnt; j++) { standards_integration_average_strenth[i, j] /= standards[i].average_times; } } //样本的平均积分平均强度 for (int i = 0; i < sample_cnt; i++) //每个标样 { if (!samples[i].is_read) { continue; } for (int t = 0; t < samples[i].average_times; t++) { double[] spec_temp_all = new double[pixel_cnt]; for (int k = 0; k < pixel_cnt; k++) { spec_temp_all[k] = spec_sample[i, t, k]; } for (int j = 0; j < element_cnt; j++) //每一个元素 { samples_integration_average_strenth[i, j] += data_util.get_integration_average(wave_all, spec_temp_all, env, elements[j].interval_start, elements[j].interval_end); } } for (int j = 0; j < element_cnt; j++) { samples_integration_average_strenth[i, j] /= samples[i].average_times; } } //显示强度,直接提取spec数组数据,根据元素(波长)积分区间来得到计算值 if (datagrid_control.show_strenth) { standard_val = standards_integration_average_strenth; sample_val = samples_integration_average_strenth; } // 当已经读取所有标样,则计算线性拟合方程,计算样本浓度 else { //所有标样都已经读取完,才需要计算样本浓度 bool is_need_calculate = true; for (int i = 0; i < standard_cnt; i++) { if (!standards[i].is_readed) { is_need_calculate = false; //标样没有全部读取完,则不需要计算方程 } for (int j = 0; j < element_cnt; j++) { standard_val[i, j] = standards[i].standard_ppm[j]; } } //样本需要根据线性方程进行计算 if (is_need_calculate) { // 根据标样浓度和对应强度计算 for (int i = 0; i < element_cnt; i++) { double[] concentration = new double[standard_cnt]; //浓度 double[] strenth = new double[standard_cnt]; for (int j = 0; j < standard_cnt; j++) { concentration[j] = standards[j].standard_ppm[i]; strenth[j] = standards_integration_average_strenth[j, i]; } LinearFit.LfReValue equation; if (bs == 0) { equation = LinearFit.linearFitFunc(concentration, strenth, standard_cnt); } else { equation = LinearFit.linearFitFunc_blank(concentration, strenth, standard_cnt); } //根据方程进行样本浓度推算 for (int j = 0; j < sample_cnt; j++) { if (!samples[j].is_read) { continue; } sample_val[j, i] = (samples_integration_average_strenth[j, i] - equation.getA()) / equation.getB(); } } } else //不需要计算时设置为0 { for (int i = 0; i < sample_cnt; i++) { for (int j = 0; j < element_cnt; j++) { sample_val[i, j] = 0; } } } } }