using DataEntity; using DataEntity.Share; using DataRWDAL; using HxSocket; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Configuration; using System.Data; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Xml; using XCommon.Image; using XCommon.Log; using XHandler.Class; using XHandler.Class.DataEx; using XHandler.Controls.DrawCanvas; using XHandler.View.ManualPick; using XHandler.View.MethodProperty; using XImagingXhandler.XDAL; using System.Windows.Media.Media3D; namespace XHandler.View.ElectroCutGum { /// /// ManualPickGum.xaml 的交互逻辑 /// public partial class ManualPickGum : Window { #region 变量 private string srcImageFile; private string jsonFile; private double startZoom; private string bacteriaTypeID; // 菌名称ID private ObservableCollection bacteriaCoordinatesSource; private ObservableCollection dgBacteriaCoordinates = new ObservableCollection(); public ExperimentRunChoiceBacteraModel expRunChoiceBactera = new ExperimentRunChoiceBacteraModel(); public event EventHandler stopEvent; public event EventHandler nextEvent; public HxSocketClient socketTcpListener = null; public bool isSimulator = false; public RunWnd launchView; // 运行窗体 public XmlNode methodNode; // 当前拍照的节点 public DataTable dtChoiceParams; // 当前成像参数 public bool cancelFlg = false; public bool isRemotingOper = false; // 是否是远程整合运行 private bool isDrawViewerInited = false; // 画图控件是否已初始化 private int countOfAutoanalysis = 0;//成像识别菌落数量 private int countOfManualchoice = 0;//人工挑选菌落数量 private int countOfManualdelete = 0;//人工删除菌落数量 private int countOfoating = 0;//涂布菌落总数 #endregion public ManualPickGum() { InitializeComponent(); } #region 构造函数 /// /// 构造函数 /// /// 拍照原图路径 /// 识别图路径 /// 识别结果json文件 /// 是否虚拟运行 public ManualPickGum(string originalImageFilePath, string imagePath, string jsonPath, bool isSimulator) { try { InitializeComponent(); srcImageFile = originalImageFilePath; jsonFile = jsonPath; this.Owner = (Window)Shared.Main; } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); } } #endregion #region 页面加载完成 private void Window_Load(object sender, RoutedEventArgs e) { try { // 获取获取挑菌参数 GetBacteriasParamInfo(); // 获取拍照json文件里的数据 bacteriaCoordinatesSource = DataModule.getInstance().GetBacteriaCoordinateList(jsonFile); LoggerHelper.InfoLog(string.Format("[ManualPickBacteria]拍照挑菌个数:{0}", bacteriaCoordinatesSource.Count())); countOfAutoanalysis = bacteriaCoordinatesSource.Count(); dgPickData.ItemsSource = dgBacteriaCoordinates; drawViewer.BackgroundImage = BitmapFrame.Create(new Uri(srcImageFile), BitmapCreateOptions.None, BitmapCacheOption.OnLoad); } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); } } #endregion #region 获取获取挑菌参数 /// /// 获取获取挑菌参数 /// private void GetBacteriasParamInfo() { string filePath = ConfigurationManager.AppSettings["choiceFilePath"]; if (!File.Exists(filePath)) { return; } // 获取挑菌参数 DataTable dtParam = ExcelAndCsvHelper.GetDataTableFromExcelFile(filePath, true); // 获取细菌信息 ObservableCollection listBacteria = DataModule.getInstance().GetBacterias(); Bacteria bacteria = listBacteria.Where(s => s.bacteria_name == this.textblockBacteriaName.Text).FirstOrDefault(); if (bacteria != null) { bacteriaTypeID = bacteria.bacteria_id; } #region 控件赋值 this.textblockTestID.Text = dtParam.Rows[0][2].ToString(); // 实验ID this.textblockBacteriaName.Text = dtParam.Rows[2][2].ToString(); // 菌名称 #endregion } #endregion private void btnClose_Click(object sender, RoutedEventArgs e) { if (EventResponseController.Instance.CanExecute() == false) return; ConfirmClose confirmClose = new ConfirmClose(); confirmClose.closeEvent += Confirm_closeEvent; confirmClose.stopEvent += ConfirmClose_stopEvent; confirmClose.skipEvent += ConfirmClose_skipEvent; Window wnd = Application.Current.MainWindow; Grid parent = Utilities.FindVisualChild(wnd); parent.Children.Add(confirmClose); } /// /// 关闭页面:控件隐藏了 /// /// /// private void ConfirmClose_skipEvent(object sender, EventArgs e) { string strDateTime = DateTime.Now.ToString("yyyyMMddTHHmmssms"); // 跳过此步,执行下一命令 SaveBacteriaResultImage(strDateTime); SaveJsonResult(strDateTime); Confirm_closeEvent(sender, EventArgs.Empty); nextEvent?.Invoke(this, EventArgs.Empty); } /// /// 保存挑菌图片 /// /// /// private string SaveBacteriaResultImage(string fileName) { string imageFilePath = string.Empty; // 保存成图片 var backgroundImage = this.drawViewer.BackgroundImage; var frame = this.drawCanvas.ToBitmapFrame(backgroundImage.PixelWidth, backgroundImage.PixelHeight, DpiHelper.GetDpiFromVisual(this.drawCanvas), backgroundImage); if (frame == null) return imageFilePath; var pickResultPath = ConfigurationManager.AppSettings["PickResultPath"]; if (!Directory.Exists(pickResultPath)) { Directory.CreateDirectory(pickResultPath); } imageFilePath = pickResultPath + fileName + ".jpg"; ImageHelper.Save(imageFilePath, frame); return imageFilePath; } /// /// 保存挑菌数据成json格式文件 /// /// /// private string SaveJsonResult(string fileName) { string jsonFilePath = string.Empty; string jsonData = File.ReadAllText(jsonFile); jsonData = jsonData.Replace("#!HxSEP!#", ""); JObject job = JObject.Parse(jsonData); job["count"] = dgBacteriaCoordinates.Count; JArray jArray = (JArray)job["germlist"]; jArray.Clear(); foreach (BacteriaCoordinateEx item in dgBacteriaCoordinates) { if (!item.canEdit) continue; JObject newObj = new JObject(); newObj.Add("index", item.bacteriacoordinate_id); newObj.Add("orgType", bacteriaTypeID); newObj.Add("diameterSize", item.diameter); newObj.Add("manualPick", item.isManualPick.ToString().ToLower()); JObject pixelObj = new JObject(); pixelObj.Add("x", item.pixelPoint.X); pixelObj.Add("y", item.pixelPoint.Y); newObj.Add("coordinatePixel", pixelObj); JObject coorObj = new JObject(); coorObj.Add("x", item.coordinate_machine.Split(',')[0]); coorObj.Add("y", item.coordinate_machine.Split(',')[1]); coorObj.Add("z", item.coordinate_machine.Split(',')[2]); newObj.Add("coordinate3D", coorObj); jArray.Add(newObj); } countOfoating = dgBacteriaCoordinates.Count; if (!isRemotingOper) { var pickResultPath = ConfigurationManager.AppSettings["PickResultPath"]; if (!Directory.Exists(pickResultPath)) { Directory.CreateDirectory(pickResultPath); } jsonFilePath = pickResultPath + fileName + ".json"; using (System.IO.StreamWriter file = new System.IO.StreamWriter(jsonFilePath)) { string data = job.ToString() + "#!HxSEP!#"; file.Write(data); } } else { var folder = System.IO.Path.Combine(Environment.CurrentDirectory, "UploadFolder"); if (!Directory.Exists(folder)) { Directory.CreateDirectory("UploadFolder"); } jsonFilePath = folder + "\\" + fileName + ".json"; using (System.IO.StreamWriter file = new System.IO.StreamWriter(jsonFilePath)) { string data = job.ToString();// + "#!HxSEP!#"; file.Write(data); } } return jsonFilePath; } /// /// 取消继续 /// /// /// private void ConfirmClose_stopEvent(object sender, EventArgs e) { // 停止当前流程 Confirm_closeEvent(sender, EventArgs.Empty); stopEvent?.Invoke(this, EventArgs.Empty); } private void Confirm_closeEvent(object sender, EventArgs e) { Window wnd = Application.Current.MainWindow; Grid grid = Utilities.FindVisualChild(wnd); UIElement element = sender as UIElement; grid.Children.Remove(element); } private void drawViewer_Loaded(object sender, RoutedEventArgs e) { try { startZoom = drawViewer.Zoom; drawCanvas.ID = 1; Point point; LoggerHelper.DebugLog(string.Format("[drawViewer_Loaded]: start draw, bacteriaCnt = {0}", bacteriaCoordinatesSource.Count())); foreach (BacteriaCoordinateEx item in bacteriaCoordinatesSource) { string[] pixels = item.coordinate_pixel.Split(','); //point = new Point((Convert.ToDouble(pixels[0]) / 1.254), (Convert.ToDouble(pixels[1]) / 1.254)); point = new Point((Convert.ToDouble(pixels[0])), (Convert.ToDouble(pixels[1]))); drawCanvas.MouseLeftButtonDown(point); // 机械坐标 string coordinateMachine = string.Format("{0},{1},{2}", item.machinePoint.X, item.machinePoint.Y, item.machinePoint.Z); drawCanvas.MouseLeftButtonUp(point, coordinateMachine); } LoggerHelper.DebugLog(string.Format("[drawViewer_Loaded]: end draw")); // 自动挑菌时,自动点击确认按钮 string choicemode = dtChoiceParams==null?"1":dtChoiceParams.Rows[9]["属性值"].ToString(); if (choicemode.Equals("0")) // 0:成像系统自动挑选菌落 { btnConfirm_Click(null, null); } } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); } finally { // 画图控件已初始化 isDrawViewerInited = true; LoggerHelper.DebugLog(string.Format("[drawViewer_Loaded]: call finished")); } } private void drawCanvas_AddPointEvent(object sender, Class.CustomRoutedEventArgs e) { try { PointData data = e.param as PointData; BacteriaCoordinateEx ex = new BacteriaCoordinateEx(); ex.bacteriacoordinate_id = data.id.ToString(); //ex.coordinate_pixel = Convert.ToInt32(Convert.ToDouble((data.point.X * 1.254).ToString("F2"))).ToString() + "," + Convert.ToInt32(Convert.ToDouble((data.point.Y * 1.254).ToString("F2"))).ToString(); ex.coordinate_pixel = Convert.ToInt32(Convert.ToDouble((data.point.X).ToString("F2"))).ToString() + "," + Convert.ToInt32(Convert.ToDouble((data.point.Y).ToString("F2"))).ToString(); ex.coordinate_machine = "0,0,0"; ex.diameter = data.diameter.ToString("F2"); ex.pixelPoint = data.point; //pixelPoint=====>machinePoint ex.machinePoint = new Point3D(0, 0, 0); ex.isManualPick = false; // 用户自己在画图上增加的,需要调用成像系统计算坐标 if (isDrawViewerInited) { Mouse.OverrideCursor = Cursors.Wait; List ret = ExecuteCalculate(ex, isSimulator); // 像素坐标转机械坐标 if (ret.Count == 2) { string dataSrc = ret[1]; string dataChg = dataSrc.Replace("#!HxSEP!#", ""); JObject job = JObject.Parse(dataChg); int iType = Convert.ToInt32(job["message_type"].ToString()); if (iType == 5) { JArray jArray = (JArray)job["data"]["result"]; ex.coordinate_machine = jArray[0]["x"].ToString() + "," + jArray[0]["y"].ToString() + "," + jArray[0]["z"].ToString(); } } Mouse.OverrideCursor = null; ex.isManualPick = true; LoggerRunHelper.InfoLog(string.Format("[ManualPickBacteria][drawCanvas_AddPointEvent]人工增加坐标: 像素坐标:{0}, 机械坐标:{1}", ex.coordinate_pixel, ex.coordinate_machine)); } else { ex.coordinate_machine = data.coordinate_machine; } dgBacteriaCoordinates.Add(ex); countOfManualchoice++; tbxCountOfSelected.Text = dgBacteriaCoordinates.Count.ToString(); } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); } } #region 像素坐标转成机械坐标 /// /// 像素坐标转成机械坐标 /// /// 像素坐标对象 /// /// 结果实体对象 private List ExecuteCalculate(BacteriaCoordinateEx bacteriaCoordinateEx, bool isSimulator = false) { // 像素坐标转成机械坐标 List strResult = socketTcpListener.SendMessage(GenerateCommand(bacteriaCoordinateEx), true); return strResult; } /// /// 像素坐标转换成机械坐标 /// /// /// private string GenerateCommand(BacteriaCoordinateEx bacteriaCoordinateEx) { string strCommand = string.Empty; try { if (bacteriaCoordinateEx != null) { string pixelGroup = bacteriaCoordinateEx.coordinate_pixel; string[] pixels = pixelGroup.Split(','); string pixelx = pixels[0]; string pixely = pixels[1]; string experimentid = "Unknown"; strCommand = "{" + "\"message_id\":\"" + Guid.NewGuid().ToString() + "\",\"message_type\":1" + ",\"method\":\"Calculate\"" + ",\"equipment_id\":\"ID2023\"" + ",\"workflow_id\":\"\"" + ",\"experiment_id\":\"" + experimentid + "\",\"parameters\":" + "{" + "\"data\":[{" + "\"x\":" + pixelx + ",\"y\":" + pixely + "}]" + "}" + ",\"process_info\":{}" + ",\"estimate_time\":5" + ",\"timeout\":60" + ",\"description\":\"NO DESC\"" + ",\"timestamp\":\"" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\"}"; } } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); } return strCommand; } #endregion private void btnClear_Click(object sender, RoutedEventArgs e) { PlsToolTipWin plsToolTipWin = new PlsToolTipWin("确定要全部删除吗?"); plsToolTipWin.ShowDialog(); if (plsToolTipWin.DialogResult != true) { return; } if (dgBacteriaCoordinates != null && dgBacteriaCoordinates.Count > 0) { foreach (BacteriaCoordinateEx bacteriaItem in dgBacteriaCoordinates) { // 删除菌落坐标 DeleteBacteriaItem(bacteriaItem); } dgBacteriaCoordinates.Clear(); tbxCountOfSelected.Text = dgBacteriaCoordinates.Count.ToString(); } } private void btnConfirm_Click(object sender, RoutedEventArgs e) { try { // 进入到手工设置板位数据 string fileName = $"{Shared.Exp.ExperimentId}_{DateTime.Now.ToString("yyyyMMddTHHmmssms")}"; string imageFilePath = SaveBacteriaResultImage(fileName); // 手工挑选之后的图 string jsonFilePath = SaveJsonResult(fileName); // 手工挑选之后的json if (launchView != null) { expRunChoiceBactera.CountAutoAnalysis = countOfAutoanalysis; expRunChoiceBactera.CountManualChoice = countOfManualchoice; expRunChoiceBactera.CountManualDelete = countOfManualdelete; expRunChoiceBactera.CountCoating = countOfoating; expRunChoiceBactera.SourceImagePath = srcImageFile; expRunChoiceBactera.UpdateImagePath = imageFilePath; expRunChoiceBactera.UpdateJsonPath = jsonFilePath; string filePath = ConfigurationManager.AppSettings["choiceFilePath"];// 挑菌下发参数.xls dtChoiceParams = ExcelAndCsvHelper.GetDataTableFromExcelFile(filePath, true); expRunChoiceBactera.BacteriaName = dtChoiceParams == null ? "" : dtChoiceParams.Rows[2]["属性值"].ToString(); expRunChoiceBactera.BacteriaColor = dtChoiceParams == null ? "" : dtChoiceParams.Rows[5]["属性值"].ToString(); expRunChoiceBactera.BacteriaEdge = dtChoiceParams == null ? "" : dtChoiceParams.Rows[4]["属性值"].ToString(); expRunChoiceBactera.BacteriaShape = dtChoiceParams == null ? "" : dtChoiceParams.Rows[3]["属性值"].ToString(); expRunChoiceBactera.BacteriaMinSize = dtChoiceParams == null ? 0 : Convert.ToDouble(dtChoiceParams.Rows[6]["属性值"].ToString()); expRunChoiceBactera.BacteriaMaxSize = dtChoiceParams == null ? 0 : Convert.ToDouble(dtChoiceParams.Rows[7]["属性值"].ToString()); expRunChoiceBactera.BacteraProx = dtChoiceParams == null ? 0 : Convert.ToDouble(dtChoiceParams.Rows[8]["属性值"].ToString()); ExperimentRunChoiceBacteraDB.Add(expRunChoiceBactera); } ChoiceConfirmNext confirmNext = new ChoiceConfirmNext(); if (isRemotingOper) // 远程整合调用中,发送挑菌结构给中控 { return; } else { this.Visibility = Visibility.Hidden; confirmNext.Height = this.ActualHeight; confirmNext.Width = this.ActualWidth; confirmNext.manualPickGum = this; confirmNext.launchView = launchView; confirmNext.methodNode = methodNode; confirmNext.dtChoiceParams = dtChoiceParams; SolidColorBrush mybtn1_Brush = new SolidColorBrush(System.Windows.Media.Color.FromArgb(0, 0, 0, 0)); confirmNext.Background = (System.Windows.Media.Brush)mybtn1_Brush; confirmNext.dgBacteriaCoordinates = dgBacteriaCoordinates; confirmNext.ShowDialog(); } cancelFlg = confirmNext.cancelFlg; } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); } } private void delete_Button_Click(object sender, RoutedEventArgs e) { try { Button btn = (Button)sender; if (btn != null) { string id = btn.Tag as string; BacteriaCoordinateEx bacteriaItem = dgBacteriaCoordinates.Where(s => s.bacteriacoordinate_id == id).FirstOrDefault(); // 删除菌落坐标 if (DeleteBacteriaItem(bacteriaItem)) { dgBacteriaCoordinates.Remove(bacteriaItem); tbxCountOfSelected.Text = dgBacteriaCoordinates.Count.ToString(); } } } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); } } /// /// 删除菌落坐标 /// /// /// private bool DeleteBacteriaItem(BacteriaCoordinateEx bacteriaItem) { if (bacteriaItem != null) { Visual dv = drawCanvas.GetVisual(Convert.ToInt32(bacteriaItem.bacteriacoordinate_id)); if (dv != null) { // 删除Visual drawCanvas.DeleteVisual(dv); // 删除DataGridItem countOfManualdelete++; LoggerRunHelper.InfoLog(string.Format("[ManualPickBacteria][DeleteBacteriaItem]: 删除坐标成功: 像素坐标:{0}, 机械坐标:{1}", bacteriaItem.coordinate_pixel, bacteriaItem.coordinate_machine)); return true; } else { LoggerRunHelper.ErrorLog(string.Format("[ManualPickBacteria][DeleteBacteriaItem]: 删除坐标失败: bacteriacoordinate_id:{0}", bacteriaItem.bacteriacoordinate_id)); return false; } } else { LoggerRunHelper.ErrorLog(string.Format("[ManualPickBacteria][DeleteBacteriaItem]: bacteriaItem = null, 删除失败!")); return false; } } private void btnZoomin_Click(object sender, RoutedEventArgs e) { try { double zoom = drawViewer.Zoom * 0.8; drawViewer.Zoom = zoom; } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); } } private void btnZoomout_Click(object sender, RoutedEventArgs e) { try { double zoom = drawViewer.Zoom * 1.2; drawViewer.Zoom = zoom; } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); } } private void btnFit_Click(object sender, RoutedEventArgs e) { try { drawViewer.Zoom = startZoom; } catch (Exception ex) { LoggerHelper.ErrorLog("ERROR:", ex); } } } }