using OTSCLRINTERFACE; using OTSDataType; using OTSModelSharp; using OTSModelSharp.ServiceCenter; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using static OTSDataType.otsdataconst; using CHoleBSEImgsList = System.Collections.Generic.List; namespace OTSMeasureApp._1_OTSMeasure.Measure._3_MeasureFlow { internal class CSmplPreviewMeasure { protected static NLog.Logger log; protected COTSSample m_HolePreviewSample; protected CMeasure m_pMsrThread; CHoleBSEImgsList m_listHoleBSEImg; protected ISemController m_SemHardwareMgr; protected IScanController m_ScanHardwareMgr; public CSmplPreviewMeasure(CMeasure a_msrThread, COTSSample a_pSample) { m_pMsrThread = a_msrThread; m_HolePreviewSample = a_pSample; log = NLog.LogManager.GetCurrentClassLogger(); var imgwidth = m_HolePreviewSample.GetMsrParams().GetImageScanParam().GetImageResolutionSize().cx; var imgheight = m_HolePreviewSample.GetMsrParams().GetImageScanParam().GetImageResolutionSize().cy; m_SemHardwareMgr = SemController.GetSEMController(); m_ScanHardwareMgr = ScanController.GetScanController(); m_listHoleBSEImg = new CHoleBSEImgsList(); } private class SEMStateObject { private PointF pos; private double workingDistance; private double magnification; public PointF Pos { get => pos; set => pos = value; } public double WorkingDistance { get => workingDistance; set => workingDistance = value; } public double Magnification { get => magnification; set => magnification = value; } } private class AutoResetSEMControl : IDisposable { CSmplPreviewMeasure sem; private SEMStateObject semState = null; public AutoResetSEMControl(SEMStateObject s, CSmplPreviewMeasure a_sem) { semState = s; sem=a_sem; } public SEMStateObject SemState { get => semState; set => semState = value; } public void Dispose() { if (semState != null) { sem.m_SemHardwareMgr.SetMagnification(semState.Magnification); Thread.Sleep(100); sem.MoveSEMToPoint(semState.Pos); Thread.Sleep(100); sem.m_SemHardwareMgr.SetWorkingDistance(semState.WorkingDistance); } log.Warn("Set SEM Exteral Off!"); sem.m_SemHardwareMgr.SetScanExternal(false); } } bool MoveSEMToPoint(System.Drawing.PointF a_poi) { // get SEM controller var pSEMController = m_SemHardwareMgr; PointF a_SEMpt = new Point(); CSEMStageData a_pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData(); int hardWareDelay = a_pCSEMStageData.GetHardWareDelay(); if (!a_pCSEMStageData.ConvertOTSToSEMCoord(a_poi, ref a_SEMpt)) { return false; } log.Info("Begin to move SEM stage to OTScoord:" + a_poi.X + "," + a_poi.Y); log.Info("Begin to move SEM stage to " + a_SEMpt.X + "," + a_SEMpt.Y); // move SEM to the position (rotation 0) if (!pSEMController.MoveSEMToPoint(a_SEMpt.X, a_SEMpt.Y)) { log.Error("MoveSEMToPoint: failed to call MoveSEMToPoint method."); return false; } if (hardWareDelay > 0) { Thread.Sleep(hardWareDelay); } return true; } public void DoHolePreview() { SEMStateObject originalStateObj= new SEMStateObject(); //----------memorize the state of sem double posX = 0, posY = 0, posR = 0; m_SemHardwareMgr.GetSemPositionXY(ref posX, ref posY, ref posR); Point pos = new Point((int)posX, (int)posY); PointF otsPos = new Point(0, 0); CSEMStageData a_pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData(); if (!a_pCSEMStageData.ConvertSEMToOTSCoord(pos, ref otsPos)) { return; } originalStateObj.Pos = otsPos; double originalWd = 0; double originalMag = 0; m_SemHardwareMgr.GetWorkingDistance(ref originalWd); m_SemHardwareMgr.GetMagnification(ref originalMag ); originalStateObj.WorkingDistance = originalWd; originalMag = Math.Max(originalMag, 1.0); // ensure magnification is not zero using (AutoResetSEMControl autoReset = new AutoResetSEMControl(originalStateObj,this)) { // let the main thread to know that this sample measurement starts CMsrSampleStatus pStatus = m_HolePreviewSample.GetMsrStatus(); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS); // set current time to current time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.START); var pSEMCtrl = m_pMsrThread.GetSEMController(); var pSEMDataMsr = m_HolePreviewSample.GetSEMDataMsr(); double dMinMag = pSEMDataMsr.GetMagnification(); // get SEM controller to set magnification and working distance if (!pSEMCtrl.SetMagnification(dMinMag)) { log.Error("DoHolePreview: fail to set magnification."); } // calculate field centers List listFieldCenter; List alllistFieldCenter; if (!CalculateUnMeasuredHoleImgCenters(m_HolePreviewSample, out alllistFieldCenter, out listFieldCenter)) {// failed to calculate field centers log.Error("DoHolePreview: failed to calculate field centers."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } // go through each field for (int i = 0; i < listFieldCenter.Count; ++i) {// check and break if stop button is clicked if (m_pMsrThread.IsMeasureStopped()) {// measure stopped log.Trace("DoHolePreview: measure thread is stopped."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.STOPPED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } // check if sample measurement completes COTSImgScanPrm pScanParam = m_HolePreviewSample.GetMsrParams().GetImageScanParam(); int nTotalFieldSize = listFieldCenter.Count; // get a field center System.Drawing.Point poiFieldCentre = listFieldCenter[i]; // move SEM to the field center if (!MoveSEMToPoint(poiFieldCentre)) {// failed to move SEM to the position log.Error("DoHolePreview: failed to move SEM to the field centre point."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } // set the BSE scan param if (!InitHoleBSEParam(m_HolePreviewSample)) { log.Error("DoHolePreview: fail to set BSE param."); } // take BSE image for the fields CBSEImgClr pBSEIamge = m_ScanHardwareMgr.AcquireBSEImage(); if (pBSEIamge == null) { // failed to acquire a BSE image log.Error("DoHolePreview: failed to acquire a BSE image."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } //BSEData ST_MSTMsg MsgFieldBSE = new ST_MSTMsg(m_HolePreviewSample); MsgFieldBSE.InitHolePreBSEDataMsg(pBSEIamge, poiFieldCentre); m_pMsrThread.SendHolePreviewMessageToMeasureGUI(MsgFieldBSE); if (pStatus.GetStatus() != OTS_MSR_SAMPLE_STATUS.INPROCESS) { // measurement failed or stopped log.Error("DoHolePreview: measurement failed or stopped."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } //save the result to project file Rectangle oImageRect = (Rectangle)pBSEIamge.GetImageRect(); CHoleBSEImg pHoleBSEImg = new CHoleBSEImg(oImageRect, poiFieldCentre); pHoleBSEImg.SetImageData(pBSEIamge.GetImageDataPtr(), oImageRect.Width, oImageRect.Height); m_listHoleBSEImg.Add(pHoleBSEImg); } pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); //calculate measure time pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED); // let main thread to know that this sample measurement completes ST_MSTMsg MsgSmplEnd = new ST_MSTMsg(m_HolePreviewSample); MsgSmplEnd.InitHolePreSampleEndMsg(); m_pMsrThread.SendHolePreviewMessageToMeasureGUI(MsgSmplEnd); } } bool CalculateUnMeasuredHoleImgCenters(COTSSample sample, out List a_allpieldcenter, out List a_listUnMsrFieldCenter) { // sample measure parameters CSampleParam pMsrParam = sample.GetMsrParams(); COTSImgScanPrm poImageScanParam = pMsrParam.GetImageScanParam(); COTSImageProcParam pImgProcParam = pMsrParam.GetImageProcessParam(); CSEMFieldData poSEMDataMsr = sample.GetSEMDataMsr(); CMsrSampleStatus pStatus = sample.GetMsrStatus(); // measured field centers list List listCompletedCenter = pStatus.GetCompletedFieldsCenter(); // field centers list manager CFieldPositionHelper pFieldMgr = new CFieldPositionHelper(); // init field centers list manager if (!pFieldMgr.Init(sample.GetMsrDomain(), poImageScanParam, 0, poSEMDataMsr, listCompletedCenter)) { log.Error("CalculateFieldsCenters: failed to init field centres list manager."); a_listUnMsrFieldCenter = new List(); a_allpieldcenter = new List(); return false; } // get field centers list a_listUnMsrFieldCenter = pFieldMgr.GetUnmeasuredFieldCentrePoints();// GetFieldCentrePoints(); a_allpieldcenter = pFieldMgr.GetFieldCentrePoints(); // ok, return TRUE return true; } bool InitHoleBSEParam(COTSSample sample) { // get scan controller var pScanController = m_ScanHardwareMgr; // scan parameters var pMsrParam = sample.GetMsrParams(); var pImgScanParam = pMsrParam.GetImageScanParam(); // get image size var nImageSizeId = pImgScanParam.GetImageResulotion(); int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId; Size sizePixelImage = RESOLUTION_VALUE[nResulotionId]; if (!pScanController.Init()) { log.Error("SetBSEParam: failed to get scan control."); return false; } // set dwell time if (!pScanController.SetDwellTime(DwellTimeLevel.Low)) { return false; } // set image size if (!pScanController.SetImageSize(sizePixelImage.Width / 2, sizePixelImage.Height / 2)) { // failed to set dwell time log.Error("SetBSEParam: failed to set ImageSize"); return false; } return true; } } }