using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using OTSModelSharp.ServiceInterface; using static OTSDataType.otsdataconst; using OTSDataType; using System.Diagnostics; using System.Drawing; using System.Threading; using OTSModelSharp.DTLBase; using OTSCLRINTERFACE; namespace OTSModelSharp { using CHoleBSEImgsList = List; class CSmplMeasure { protected static NLog.Logger log ; protected bool bSaveThreadWorking; protected System.Threading.Thread m_thread_ptr; protected COTSSample m_Sample; protected CMeasure m_pMsrThread; string m_strWorkingFolder; protected CSmplMsrResult m_pSampleRstFile; CHoleBSEImgsList m_listHoleBSEImg; //CFunExportClass loger; protected SemController m_SemHardwareMgr; protected ScanController m_ScanHardwareMgr; protected EDSController m_EDSHardwareMgr; protected Queue fieldQueue=new Queue(); protected COTSFieldData curFldData; protected IClassifyEngine m_classifyEngine; public CSmplMeasure() { log = NLog.LogManager.GetCurrentClassLogger(); m_pSampleRstFile = new CSmplMsrResult(); m_SemHardwareMgr = new SemController(); m_ScanHardwareMgr = new ScanController(); m_EDSHardwareMgr = new EDSController(); m_listHoleBSEImg = new CHoleBSEImgsList(); } public CSmplMeasure( string a_strWorkingFolder, COTSSample a_pSample) { log = NLog.LogManager.GetCurrentClassLogger(); m_strWorkingFolder = a_strWorkingFolder; m_pSampleRstFile = new CSmplMsrResult( a_strWorkingFolder, a_pSample);// new CSmplMsrResultFile(m_strWorkingFolder,a_pSample); m_SemHardwareMgr = new SemController(); m_ScanHardwareMgr = new ScanController(); m_EDSHardwareMgr = new EDSController(); m_listHoleBSEImg = new CHoleBSEImgsList(); m_Sample = a_pSample; } public void SetSample(COTSSample a_pSample) { m_Sample = a_pSample; m_pSampleRstFile.SetSample(a_pSample); } public void SetMsrThread(CMeasure mt) { m_pMsrThread = mt; } bool SetSEMDataMrs() { var pSEMDataMsr = m_Sample.GetSEMDataMsr(); //ASSERT(pSEMDataMsr); double dMag = pSEMDataMsr.GetMagnification(); double dWorkDis = pSEMDataMsr.GetWorkingDistance(); //CSemBasePtr pSEMCtrlPtr = GetSEMControl(); var pSEMCtrl = m_pMsrThread.GetSEMController(); // get SEM controller if (!pSEMCtrl.IsConnected()) { if (!pSEMCtrl.Connect()) { log.Error("SetSEMDataMrs: can't connect SEM."); return false; } } log.Info("set magnification:" + dMag.ToString()); log.Info("set Working Distance:" + dWorkDis.ToString()); pSEMCtrl.SetMagnification(dMag); pSEMCtrl.SetWorkingDistance(dWorkDis); return true; } bool SetSEMExteralOn() { var pSEMCtrl = m_SemHardwareMgr; // get SEM controller if (!pSEMCtrl.IsConnected()) { if (!pSEMCtrl.Connect()) { log.Error("SetSEMExteralOn: can't connect SEM."); return false; } } log.Warn("Set Scan Exteral on!"); pSEMCtrl.SetScanExternal(true); return true; } // set SEM external off bool SetSEMExteralOff() { var pSEMCtrlPtr = m_SemHardwareMgr; // get SEM controller if (!pSEMCtrlPtr.IsConnected()) { if (!pSEMCtrlPtr.Connect()) { log.Error("SetSEMExteralOff: can't connect SEM."); return false; } } log.Warn("Set SEM Exteral Off!"); pSEMCtrlPtr.SetScanExternal(false); return true; } bool SetBSEParam() { // get SEM controller var pSEMController = m_SemHardwareMgr; // get scan controller var pScanController = m_ScanHardwareMgr; // scan parameters var pMsrParam = m_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]; // get SEM controller if (!pSEMController.IsConnected()) { if (!pSEMController.Connect()) { log.Error("SetBSEParam: can't connect SEM."); return false; } } // get dwell time OTS_IMAGE_SCANSPEED_OPTIONS nDwellTime = pImgScanParam.GetScanImageSpeed(); // convert dwell time to bruker dwell time (8, 16, 32) int nBrukerDwellTimeId=3; switch (nDwellTime) { case OTS_IMAGE_SCANSPEED_OPTIONS.low: nBrukerDwellTimeId = 3; break; case OTS_IMAGE_SCANSPEED_OPTIONS.meddium: nBrukerDwellTimeId = 4; break; case OTS_IMAGE_SCANSPEED_OPTIONS.high: nBrukerDwellTimeId = 5; break; default: nBrukerDwellTimeId = 3; break; } long nBrukerDwellTime = OTSDataType.otsdataconst.DWELLTIME_BRUKER_VALUES[nBrukerDwellTimeId]; if (!pScanController.Init()) { log.Error("SetBSEParam: failed to get scan control."); return false; } // set dwell time if (!pScanController.SetDwellTime(nBrukerDwellTime)) { log.Error("SetBSEParam: failed to set dwell time (%d) for bruker system.", nBrukerDwellTime); return false; } // set image size if (!pScanController.SetImageSize(sizePixelImage.Width,sizePixelImage.Height)) { // failed to set dwell time log.Error("SetBSEParam: failed to set dwell time (%d).", sizePixelImage.Height); return false; } return true; } bool SetHoleBSEParam() { // get SEM controller var pSEMController = m_SemHardwareMgr; // get scan controller var pScanController = m_ScanHardwareMgr; // scan parameters var pMsrParam = m_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]; // get SEM controller if (!pSEMController.IsConnected()) { if (!pSEMController.Connect()) { log.Error("SetBSEParam: can't connect SEM."); return false; } } // get dwell time OTS_IMAGE_SCANSPEED_OPTIONS nDwellTime = pImgScanParam.GetScanImageSpeed(); // convert dwell time to bruker dwell time (6, 16, 32) long nBrukerDwellTime = DWELLTIME_BRUKER_VALUES[2];// choose the third option, so the dwell time will be 4 . there's no need to change here. it shoud be a const. if (!pScanController.Init()) { log.Error("SetBSEParam: failed to get scan control."); return false; } // set dwell time if (!pScanController.SetDwellTime(nBrukerDwellTime)) { log.Error("SetBSEParam: failed to set dwell time (%d) for bruker system.", nBrukerDwellTime); 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 dwell time (%d).", sizePixelImage.Height); return false; } return true; } public void SetWorkingFolder(String a_strWorkingFolder) { // add "\\" at the string end if it is not "\\" if (a_strWorkingFolder.PadRight(1)!="\\") { a_strWorkingFolder += "\\"; } m_strWorkingFolder = a_strWorkingFolder + m_Sample.GetName() + "\\"; } bool CalculateUnMeasuredFieldsCenters(out List a_allpieldcenter,out List a_listFieldCenter) { // sample measure parameters CSampleParam pMsrParam = m_Sample.GetMsrParams(); COTSImgScanPrm poImageScanParam = pMsrParam.GetImageScanParam(); CSEMDataMsr poSEMDataMsr = m_Sample.GetSEMDataMsr(); CMsrSampleStatus pStatus = m_Sample.GetMsrStatus(); // measured field centers list List listCompletedCenter = pStatus.GetCompletedFieldsCenter(); // field centers list manager CFieldPositionMgr pFieldMgr = new CFieldPositionMgr(); // init field centers list manager if (!pFieldMgr.Init(m_Sample.GetMsrArea(), poImageScanParam, poSEMDataMsr, listCompletedCenter)) { log.Error("CalculateFieldsCenters: failed to init field centres list manager."); a_listFieldCenter = new List(); a_allpieldcenter = new List(); return false; } // get field centers list a_listFieldCenter = pFieldMgr.GetUnmeasuredFieldCentrePoints();// GetFieldCentrePoints(); a_allpieldcenter = pFieldMgr.GetFieldCentrePoints(); // ok, return TRUE return true; } protected bool IsAborted() { //Debug.Assert(m_pMsrThread == null); return m_pMsrThread.IsMeasureStopped(); } bool IsSampleOver(COTSImgScanPrm a_pScanParam, int a_nTotalFields) { int nStopMode = (int)a_pScanParam.GetStopMode(); int nStopField = a_pScanParam.GetStopParamFields(); // completed fields number CMsrSampleStatus pMsrSampleStatus = m_Sample.GetMsrStatus(); int nCompeltedField = pMsrSampleStatus.GetCompletedFields(); CMsrDisplayResults pMsrResults = m_Sample.GetMsrResults(); List listMsrResult = pMsrResults.GetResultItems(); int nNumParticle = 0; foreach (var pResult in listMsrResult) { if (pResult.GetTypeId() > (int)OTS_PARTCLE_TYPE.NO_ANALYSIS_X_RAY)//summarize the number of the identified particle in this condition { nNumParticle += (int)pResult.GetNumber(); } } TimeSpan timeSpan = pMsrSampleStatus.GetUsedTime(); int nDay = timeSpan.Days; int nHour = timeSpan.Hours; int nMin = timeSpan.Minutes; int nSec = timeSpan.Seconds; int nUsedTime = nSec + nMin * 60 + nHour * 3600 + nDay * 86400; int nParticlAim = a_pScanParam.GetStopParamParticles(); int nMeasTimeAim = a_pScanParam.GetStopParamMeasTime(); bool bRet = true; switch (nStopMode) { case (int)OTS_MEASURE_STOP_MODE.CoverMode: // completed fields number if (nCompeltedField < a_nTotalFields) { bRet = false; } break; case (int)OTS_MEASURE_STOP_MODE.FieldMode: if (nCompeltedField < nStopField) { bRet = false; } break; case (int)OTS_MEASURE_STOP_MODE.ParticleMode: if (nNumParticle < nParticlAim) { bRet = false; } break; case (int)OTS_MEASURE_STOP_MODE.TimeMode: if (nUsedTime < nMeasTimeAim) { bRet = false; } break; default: break; } return bRet; } // move SEM to the point bool MoveSEMToPoint(System.Drawing.Point a_poi) { //add // get SEM controller var pSEMController = m_SemHardwareMgr; Point a_SEMpt = new Point(); CSEMStageData a_pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData(); if (!a_pCSEMStageData.ConverOTSToSEMPoint(a_poi, ref a_SEMpt)) { return false; } if (!pSEMController.IsConnected()) { if (!pSEMController.Connect()) { log.Error("MoveSEMToPoint: can't connect SEM."); return false; } } log.Info("Begin to move SEM stage to " + a_SEMpt.X + "," + a_SEMpt.Y); Thread.Sleep(100); // move SEM to the position (rotation 0) if (!pSEMController.MoveSEMToPoint(a_SEMpt, 0)) { log.Error("MoveSEMToPoint: failed to call MoveSEMToPoint method."); return false; } //add return true; } // Acquire a BSE image CBSEImgClr AcquireABSEImage() { // BSE image CBSEImgClr pBSEImage = null; // get scan controller var pScanController = m_ScanHardwareMgr; pBSEImage = pScanController.AcquireBSEImage(0, 0, 2); return pBSEImage; } public virtual bool FieldImageProcess(Point fldCenter, CBSEImgClr imageData) { return true; } public virtual void ClassifyFieldParticles() { return; } public virtual void ClassifyMergedParticles(List parts) { return; } private class AutoResetSEMControl:IDisposable { CSmplMeasure sm; public AutoResetSEMControl(CSmplMeasure s) { sm = s; } public void Dispose() { sm.SetSEMExteralOff(); } } public void DoMeasureForOneSample() { using (AutoResetSEMControl autoReset = new AutoResetSEMControl(this)) //when this method exit ,the SetSEMExternalOff and ResetScan will be called automatically. { // let the main thread to know that this sample measurement starts var pStatus = m_Sample.GetMsrStatus(); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS); // set current time to current time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.START); // let main App know that the sample begin to measure ST_MSTMsg MsgSmpStart = new ST_MSTMsg(); MsgSmpStart.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS; MsgSmpStart.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.INPROCESS; MsgSmpStart.STMSampleStu.cSampleName = m_Sample.GetName(); m_pMsrThread.SendMessageToMeasureApp(MsgSmpStart); log.Info(m_Sample.GetName() + " Measurement started!"); // get SEM controller to set magnification and working distance if (!SetSEMDataMrs()) { log.Error("DoMeasure: fail to set SEM data."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } // get SEM external controll on if (!SetSEMExteralOn()) { log.Error("DoMeasure: fail to set SEM external."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } // set the BSE scan param if (!SetBSEParam()) { log.Error("DoMeasure: fail to set BSE param."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } var pSEMDataGnr = new CSEMDataGnr(); log.Info("Get Kv, Brightness and Contrast!"); m_SemHardwareMgr.GetSEMDataGnrFromHw(ref pSEMDataGnr); m_pSampleRstFile.SetSEMGnr(pSEMDataGnr); // record SEM data COTSMsrPrjResultData pProjMgrFile = m_pMsrThread.GetProjResultData(); CSEMStageData pSEMStageData = pProjMgrFile.GetSEMStageData(); m_pSampleRstFile.SetSEMStageData(pSEMStageData); // record stage CStage pStage = pProjMgrFile.GetStage(); m_pSampleRstFile.SetSEMStage(pStage); // calculate field centers List umMeasuredlistFieldCenter; List alllistFieldCenter; if (!CalculateUnMeasuredFieldsCenters(out alllistFieldCenter,out umMeasuredlistFieldCenter)) {// failed to calculate field centers log.Error("DoMeasure: failed to calculate field centers."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } //-----save the static measure result file data into xml file and the dynamic data of every field will be saved into sqlite database log.Info("Create result file!"); if (!m_pSampleRstFile.CreateResultFiles()) {// failed to call measure result file Save method log.Error("DoMeasure: failed to call measure result file Save method."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } //------ int nNewFieldId = 0; int numOfAllFields = pStatus.GetCompletedFields() + umMeasuredlistFieldCenter.Count;// int completedFields = pStatus.GetCompletedFields(); log.Info("Unmeasured fields:" + umMeasuredlistFieldCenter.Count); for (int i = 0; i < (int)umMeasuredlistFieldCenter.Count; ++i) {// check and break if stop button is clicked if (IsAborted()) {// measure stopped pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.STOPPED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); //must wait for the saving data thread finished,or we'll get null pointer exception when we stop the measure process. while (fieldQueue.Count() > 0) { Thread.Sleep(100); } return; } // check if sample measurement completes COTSImgScanPrm pScanParam = m_Sample.GetMsrParams().GetImageScanParam(); int nTotalFieldSize = (int)umMeasuredlistFieldCenter.Count; if (IsSampleOver(pScanParam, numOfAllFields)) { pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); break; } // get a field center System.Drawing.Point poiFieldCentre = umMeasuredlistFieldCenter[i]; // update thread measure status class, let the main thread know that starts a new field ST_MSTMsg MsgFieldStart = new ST_MSTMsg(); MsgFieldStart.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT; MsgFieldStart.STMSampleRetData.iRetDataType = MSAMPLE_RET.START_MSR_FIELD; MsgFieldStart.STMSampleRetData.SMsrField.FieldPos = poiFieldCentre; m_pMsrThread.SendMessageToMeasureApp(MsgFieldStart); int fldNo = completedFields + i + 1; log.Warn("Current field:" + fldNo.ToString()); // move SEM to the field center if (!MoveSEMToPoint(poiFieldCentre)) {// failed to move SEM to the position log.Error("DoMeasure: 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; } log.Info("Begin to Acquire BSE image!"); // take BSE image for the fields CBSEImgClr pBSEImg = AcquireABSEImage(); // let the main thread to know that image process is completed if (pBSEImg == null) { log.Error("ImageProcess: can't get no background image."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); return; } //BSEData ST_MSTMsg MsgFieldBSE = new ST_MSTMsg(); MsgFieldBSE.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT; MsgFieldBSE.STMSampleRetData.iRetDataType = MSAMPLE_RET.BSE_DATA; MsgFieldBSE.STMSampleRetData.BSEData.pos.X = poiFieldCentre.X; MsgFieldBSE.STMSampleRetData.BSEData.pos.Y = poiFieldCentre.Y; MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight = pBSEImg.GetHeight(); MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth = pBSEImg.GetWidth(); byte[] pImgData = pBSEImg.GetImageDataPtr(); MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = pImgData; m_pMsrThread.SendMessageToMeasureApp(MsgFieldBSE); // get a new field id log.Info("Acquire BSE image success! Processing image..."); // image process var rst = FieldImageProcess(poiFieldCentre, pBSEImg); if (rst == true) { // add the field into the field m_pSampleRstFile.AddAField(curFldData); } ++nNewFieldId; double measuredArea = 0; // this area should be the field area var a_pBSEImg = curFldData.GetBSEImage(); double dPixelSize = m_Sample.CalculatePixelSize(); measuredArea = a_pBSEImg.GetHeight() * a_pBSEImg.GetWidth()* dPixelSize * dPixelSize + 0.5; //Get measured area if (!CumulateFieldData(curFldData.GetListAnalysisParticles(), measuredArea)) { // failed to call SaveFieldFile method log.Error("ImageProcess: call CumulateFieldData method."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); return; } log.Info("Send field data to screen!"); // completed fields pStatus.SetCompletedFields(pStatus.GetCompletedFields() + 1); // completed fieldCenter List listCpltedCenter = pStatus.GetCompletedFieldsCenter(); listCpltedCenter.Add(poiFieldCentre); //Field Data // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); ST_MSTMsg MsgFieldEnd = new ST_MSTMsg(); MsgFieldEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT; MsgFieldEnd.STMSampleRetData.iRetDataType = MSAMPLE_RET.FIELD_DATA; MsgFieldEnd.STMSampleRetData.SFieldData.iCompleteFieldCount = pStatus.GetCompletedFields(); MsgFieldEnd.STMSampleRetData.SFieldData.iMeasureFieldCount = numOfAllFields; MsgFieldEnd.STMSampleRetData.SFieldData.iSParticleCount = (int)curFldData.GetListAnalysisParticles().Count; MsgFieldEnd.STMSampleRetData.SFieldData.FieldPos.X = Convert.ToInt32(poiFieldCentre.X); MsgFieldEnd.STMSampleRetData.SFieldData.FieldPos.Y = Convert.ToInt32(poiFieldCentre.Y); m_pMsrThread.SendMessageToMeasureApp(MsgFieldEnd); } while (bSaveThreadWorking)//wait untill all the field data has been saved. { Thread.Sleep(1000); log.Info("db saving!"); } //merging particles log.Info("Merging big particles which are crossing the field edge!"); CImageHandler imgpro = new CImageHandler(); int scanfldsize = m_Sample.GetSEMDataMsr().GetScanFieldSize(); List mergedParticles = new List(); double pixelSize = m_Sample.CalculatePixelSize(); imgpro.MergeBigBoundaryParticles(m_pSampleRstFile.GetFieldData(), pixelSize, scanfldsize, m_Sample.GetResolutionSize(), ref mergedParticles); CalculateMergedPartProperty(mergedParticles,pixelSize); ClassifyMergedParticles(mergedParticles); log.Warn("begin particle data db saving..."); SaveMergedParticles(mergedParticles); pStatus.ComputeTime(OTS_MSR_TIME_TYPE.COMPLT); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED); // let main thread to know that this sample measurement completes ST_MSTMsg MsgSmplEnd = new ST_MSTMsg(); MsgSmplEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS; MsgSmplEnd.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.SUCCESSED; MsgSmplEnd.STMSampleStu.cSampleName = m_Sample.GetName(); m_pMsrThread.SendMessageToMeasureApp(MsgSmplEnd); } } private void CalculateMergedPartProperty(List mergedParticles,double pixelSize) { var m_ImagePro = new CImageHandler(); foreach (COTSParticleClr part in mergedParticles) { m_ImagePro.CalParticleImageProp(part, pixelSize); } } public void DoHolePreview(int a_nHoleID) { using (AutoResetSEMControl autoReset = new AutoResetSEMControl(this)) { // let the main thread to know that this sample measurement starts CMsrSampleStatus pStatus = m_Sample.GetMsrStatus(); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS); // set current time to current time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.START); // let main App know that the sample begin to measure ST_MSTMsg MsgSmpStart=new ST_MSTMsg(); MsgSmpStart.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS; MsgSmpStart.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.INPROCESS; MsgSmpStart.STMSampleStu.cSampleName=m_Sample.GetName(); // get SEM controller to set magnification and working distance if (!SetSEMDataMrs()) { log.Error("DoHolePreview: fail to set SEM data."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } // get SEM external controll on if (!SetSEMExteralOn()) { log.Error("DoMeasure: fail to set SEM external."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } // set the BSE scan param if (!SetHoleBSEParam()) { log.Error("DoMeasure: fail to set BSE param."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } // check if measurement is aborted if (IsAborted()) {// measurement aborted log.Trace("DoHolePreview: measurement aborted before get SEM condition."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.STOPPED); // record end time pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } // calculate field centers List listFieldCenter=new List(); List alllistFieldCenter = new List(); // listFieldCenter.clear(); if (!CalculateUnMeasuredFieldsCenters(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 int nNewFieldId = 0; for ( int i = 0; i < listFieldCenter.Count; ++i) {// check and break if stop button is clicked if (IsAborted()) {// 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_Sample.GetMsrParams().GetImageScanParam(); int nTotalFieldSize = listFieldCenter.Count; if (IsSampleOver(pScanParam, nTotalFieldSize)) { pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); break; } // get a field center System.Drawing.Point poiFieldCentre = listFieldCenter[i]; // update thread measure status class, let the main thread know that starts a new field pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); ST_MSTMsg MsgFieldStart=new ST_MSTMsg(); //memset(&MsgFieldStart, 0, sizeof(ST_MSTMsg)); MsgFieldStart.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT; MsgFieldStart.STMSampleRetData.iRetDataType = MSAMPLE_RET.START_MSR_FIELD; MsgFieldStart.STMSampleRetData.SMsrField.FieldPos = poiFieldCentre; m_pMsrThread.SendMessageToMeasureApp(MsgFieldStart); // 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; } // take BSE image for the fields CBSEImgClr pBSEIamge = AcquireABSEImage(); 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(); // memset(&MsgFieldBSE, 0, sizeof(ST_MSTMsg)); MsgFieldBSE.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT; MsgFieldBSE.STMSampleRetData.iRetDataType = MSAMPLE_RET.BSE_DATA; MsgFieldBSE.STMSampleRetData.BSEData.pos = poiFieldCentre; //MsgFieldBSE.STMSampleRetData.BSEData.pos.y = poiFieldCentre.y; MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight = pBSEIamge.GetHeight(); MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth = pBSEIamge.GetWidth(); byte[] pImgData = pBSEIamge.GetImageDataPtr(); MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = pImgData; m_pMsrThread.SendMessageToMeasureApp(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 CHoleBSEImg pHoleBSEImg =new CHoleBSEImg(); pHoleBSEImg.SetHoleID(a_nHoleID); pHoleBSEImg.SetPosition(poiFieldCentre); Rectangle oImageRect =(Rectangle) pBSEIamge.GetImageRect(); int nImageSize = pBSEIamge.GetHeight() * pBSEIamge.GetWidth(); pHoleBSEImg.SetImageRect(oImageRect); pHoleBSEImg.SetImageData( pBSEIamge.GetImageDataPtr(),oImageRect.Width,oImageRect.Height); m_listHoleBSEImg.Add(pHoleBSEImg); COTSMsrPrjResultData pProjMgrFile = m_pMsrThread.GetProjResultData(); pProjMgrFile.SetHoleBESImgList(m_listHoleBSEImg,true); // prepare for the next ++nNewFieldId; pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); ST_MSTMsg MsgFieldEnd=new ST_MSTMsg(); MsgFieldEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT; MsgFieldEnd.STMSampleRetData.iRetDataType = MSAMPLE_RET.FIELD_DATA; MsgFieldEnd.STMSampleRetData.SFieldData.iCompleteFieldCount = (i + 1); MsgFieldEnd.STMSampleRetData.SFieldData.iMeasureFieldCount = listFieldCenter.Count; MsgFieldEnd.STMSampleRetData.SFieldData.iSParticleCount = 0; MsgFieldEnd.STMSampleRetData.SFieldData.FieldPos = poiFieldCentre; m_pMsrThread.SendMessageToMeasureApp(MsgFieldEnd); //break; } 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(); MsgSmplEnd.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS; MsgSmplEnd.STMThreadStu.iMsrStatu = OTS_MSR_THREAD_STATUS.COMPLETED; m_pMsrThread.SendMessageToMeasureApp(MsgSmplEnd); } } // Cumulate field data info public virtual bool CumulateFieldData( List listParticles, double a_nMeasuredArea) { // get measure result items of the sample CMsrDisplayResults pMsrResults = m_Sample.GetMsrResults(); // cumulate field data info //pMsrResults.CumulateMeasureResults(listResultItems); pMsrResults.CumulateMeasuredArea(a_nMeasuredArea); // cumulate ratio double dRatio = 10000 * pMsrResults.GetTotalParticleArea(); dRatio = dRatio / pMsrResults.GetMeasuredArea(); pMsrResults.SetRatio(dRatio); // go through the particles list foreach (COTSParticleClr pParticle in listParticles) { // create a measure result item pMsrResults.CumulateMeasureResult(pParticle); } // ok, return TRUE return true; } // hole BSE images list void SetHoleBESImgList(CHoleBSEImgsList a_listHoleBSEImg, bool a_bClear/* = TRUE*/) {// clear the hole BSE image list if necessary if (a_bClear) { m_listHoleBSEImg.Clear(); } // go through the input list foreach (var pHoleBSEImg in a_listHoleBSEImg) {// add the new hole BSE image into HoleBSEImage list m_listHoleBSEImg.Add(pHoleBSEImg); } } public bool SaveMergedParticles(List mergedParts) { CIncAFileMgr pDBFileMgr = m_pSampleRstFile.DBFileMgr; var mergedpartdb = pDBFileMgr.GetMergedParticleDB(); foreach (COTSParticleClr part in mergedParts) { mergedpartdb.SaveAParticle(part, part.GetXray(), (Point)part.GetAbsolutPos()); } CPosXrayDBMgr pXrayDBMgr = pDBFileMgr.GetPosXrayDBMgr(); CElementChemistryDB xraydb = pXrayDBMgr.GetElementChemistryDB(); List ches = new List(); foreach (COTSParticleClr part in mergedParts) { ches.Add(part.GetXray()); } xraydb.SaveElementChemistriesList(ches); return true; } } }