using System; using System.Collections.Generic; using System.Linq; using OTSModelSharp.ServiceCenter; using static OTSDataType.otsdataconst; using OTSDataType; using System.Drawing; using System.Threading; using OTSCLRINTERFACE; using OTSMeasureApp._1_OTSMeasure.Measure._3_MeasureFlow; using OTSMeasureApp._0_OTSModel.OTSDataType; namespace OTSModelSharp { public 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; internal ISemController m_SemHardwareMgr; internal IScanController m_ScanHardwareMgr; internal IEDSController m_EDSController; protected Queue fieldQueue=new Queue(); protected IClassifyEngine m_classifyEngine; private bool m_ifAquireClearParticleImage=false; public CSmplMeasure( string a_strWorkingFolder, COTSSample a_pSample) { m_Sample = a_pSample; log = NLog.LogManager.GetCurrentClassLogger(); var expC = m_Sample.GetMsrParams().GetXRayParam().GetAnalyExpCount(); var imgwidth = m_Sample.GetMsrParams().GetImageScanParam().GetImageResolutionSize().cx; var imgheight = m_Sample.GetMsrParams().GetImageScanParam().GetImageResolutionSize().cy; m_strWorkingFolder = a_strWorkingFolder; m_pSampleRstFile = new CSmplMsrResult( a_strWorkingFolder, a_pSample); m_SemHardwareMgr = SemController.GetSEMController(); m_ScanHardwareMgr = ScanController.GetScanController(); var ifautoid = m_Sample.GetMsrParams().GetXRayParam().IfAutoId; var knownelements = m_Sample.GetMsrParams().GetXRayParam().AnalysisElements; m_EDSController = EDSController.GetEDSController(imgwidth,imgheight,expC,ifautoid,knownelements); m_ifAquireClearParticleImage = FileHelper.GetIfAquireClearParticleImage(); } public void SetSample(COTSSample a_pSample) { m_Sample = a_pSample; m_pSampleRstFile.SetSample(a_pSample); } public COTSSample GetSample() { return m_Sample; } public void SetMsrThread(CMeasure mt) { m_pMsrThread = mt; } bool SetSEMDataMrs(CSEMFieldData pSEMDataMsr) { //var pSEMDataMsr = sample.GetSEMDataMsr(); double dMag = pSEMDataMsr.GetMagnification(); double dWorkDis = pSEMDataMsr.GetWorkingDistance(); double bri=pSEMDataMsr.Brightness; double contra = pSEMDataMsr.Contrast; try { var pSEMCtrl = m_pMsrThread.GetSEMController(); pSEMCtrl.SetMagnification(dMag); pSEMCtrl.SetWorkingDistance(dWorkDis); //pSEMCtrl.SetSemBrightness(bri); //pSEMCtrl.SetSemContrast(contra); log.Warn("set magnification " + dMag); log.Warn("set wd "+ dWorkDis); //log.Warn("set brightness "+bri); //log.Warn("set contrast "+contra); } catch (Exception e) { log.Error(e.Message); } return true; } // set SEM external off bool SetSEMExteralOff() { var pSEMCtrlPtr = m_SemHardwareMgr; log.Warn("Set SEM Exteral Off!"); pSEMCtrlPtr.SetScanExternal(false); return true; } internal bool InitScanControllerBSEParam() { // 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 dwell time OTS_IMAGE_SCANSPEED_OPTIONS nDwellTime = pImgScanParam.GetScanImageSpeed(); // convert dwell time to bruker dwell time DwellTimeLevel DwellTimeId; switch (nDwellTime) { case OTS_IMAGE_SCANSPEED_OPTIONS.low: DwellTimeId = DwellTimeLevel.Low; break; case OTS_IMAGE_SCANSPEED_OPTIONS.meddium: DwellTimeId = DwellTimeLevel.Medium; break; case OTS_IMAGE_SCANSPEED_OPTIONS.high: DwellTimeId = DwellTimeLevel.High; break; default: DwellTimeId = DwellTimeLevel.Low; break; } if (!pScanController.Init()) { log.Error("InitScanControllerBSEParam: failed to get scan control."); return false; } // set dwell time if (!pScanController.SetDwellTime(DwellTimeId)) { return false; } // set image size if (!pScanController.SetImageSize(sizePixelImage.Width,sizePixelImage.Height)) { // failed to set dwell time log.Error("InitScanControllerBSEParam: 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() + "\\"; } protected bool IsAborted() { return m_pMsrThread.IsMeasureStopped(); } protected bool IsPaused() { var statu = m_pMsrThread.GetMsrThreadStatus(); if (statu.GetStatus() == OTS_MSR_THREAD_STATUS.PAUSED) { return true; } else { return false; } } bool IsSampleOver(COTSImgScanPrm a_pScanParam) { string sStopMode = a_pScanParam.GetStopMode(); int nStopField = a_pScanParam.GetStopParamFields(); // completed fields number CMsrSampleStatus pMsrSampleStatus = m_Sample.GetMsrStatus(); int nCompeltedField = pMsrSampleStatus.GetCompletedFields(); CMsrResultItems pMsrResults = m_Sample.GetMsrResults(); List listMsrResult = pMsrResults.GetResultItems(); int nNumParticle = 0; foreach (var pResult in listMsrResult) { if (pResult.GetTypeId() > (int)OTS_PARTICLE_TYPE.NOT_IDENTIFIED)//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 NMeasArea = (int)pMsrResults.GetMeasuredArea(); int nParticlAim = a_pScanParam.GetStopParamParticles(); int nMeasTimeAim = a_pScanParam.GetStopParamMeasTime(); int NMeasAreaAim = a_pScanParam.GetStopParamArea()*1000000 ; bool bRet = false; string[] str = sStopMode.Replace(" ", "").Split('+'); for(int i=0;i< str.Length;i++) { switch (int.Parse(str[i].Split(':')[0])-1) { case (int)OTS_MEASURE_STOP_MODE.CoverMode: // completed fields number if (nCompeltedField == m_Sample.GetFieldsData().Count) { bRet = true; } break; case (int)OTS_MEASURE_STOP_MODE.FieldMode: if (nCompeltedField >= nStopField) { bRet = true; } break; case (int)OTS_MEASURE_STOP_MODE.ParticleMode: if (nNumParticle >= nParticlAim) { bRet = true; } break; case (int)OTS_MEASURE_STOP_MODE.TimeMode: if (nUsedTime >= nMeasTimeAim) { bRet = true; } break; case (int)OTS_MEASURE_STOP_MODE.AreaMode: if (NMeasArea >= NMeasAreaAim) { bRet = true; } break; default: break; } } return bRet; } // move SEM to the point internal 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; } CSampleParam pMsrParam = m_Sample.GetMsrParams(); if (pMsrParam.SlopParam.IsUsingSlopParam) { double wd = pMsrParam.SlopParam.GetWD(a_SEMpt); double originWd = 0; pSEMController.GetWorkingDistance(ref originWd); if ((wd - originWd) > 2) { log.Warn("Working Distance is invalid,outof the moving scope(2cm) wd=" + wd.ToString("F2")); } else { Thread.Sleep(hardWareDelay); pSEMController.SetWorkingDistance(wd); } } if (hardWareDelay > 0) { Thread.Sleep(hardWareDelay); } return true; } // Acquire a BSE image CBSEImgClr AcquireABSEImage() { // BSE image CBSEImgClr pBSEImage = null; // get scan controller var pScanController = m_ScanHardwareMgr; pBSEImage = pScanController.AcquireBSEImage(); return pBSEImage; } public bool IsLowCounts(COTSParticleClr particle) { COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam(); if (pXRayParam.GetUsingXray() == true) { var thecount = particle.GetXray().GetTotalCount(); var expect = pXRayParam.GetAnalyExpCount(); if (thecount < expect) { particle.SetType((int)OTS_PARTICLE_TYPE.LOW_COUNT); particle.SetClassifyId((int)OTS_PARTICLE_TYPE.LOW_COUNT); particle.SetTypeColor("#000000"); particle.SetTypeName("LowCounts"); return true; } } return false; } public virtual void ClassifyFieldParticles(COTSField curFldData) { return; } private bool GetSEMDataGnrFromHw(ref CSEMDataGnr SemDataGnr) { double kv = 0, brightness = 0, contrast = 0; var hw = SemController.GetSEMController(); hw.GetSemHighTension(ref kv); hw.GetSemBrightness(ref brightness); hw.GetSemContrast(ref contrast); SemDataGnr.SetValue(kv, brightness, contrast); return true; } public void DoMeasureForOneSample() { try { // 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(m_Sample); MsgSmpStart.InitSampleStartMsg(); m_pMsrThread.SendMessageToMeasureGUI(MsgSmpStart); log.Info(m_Sample.GetName() + " Measurement started!"); // get SEM controller to set magnification and working distance if (!SetSEMDataMrs(m_Sample.GetSEMDataMsr())) { log.Error("DoMeasure: fail to set SEM data."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); return; } // set the BSE scan param if (!InitScanControllerBSEParam()) { 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 current Kv, Brightness and Contrast!"); GetSEMDataGnrFromHw(ref pSEMDataGnr); m_pSampleRstFile.SetSEMDataGnr(pSEMDataGnr); // record SEM data COTSMsrPrjResultData pProjMgrFile = m_pMsrThread.GetProjResultData(); CSEMStageData pSEMStageData = pProjMgrFile.GetSEMStageData(); m_pSampleRstFile.SetSEMStageData(pSEMStageData); CSampleHolder pSampleStage = pProjMgrFile.GetStageHolder(); m_pSampleRstFile.SetSEMStage(pSampleStage); //-----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; } //------ var FldDatas = m_Sample.GetFieldsData(); for (int i = 0; i < FldDatas.Count; ++i) {// check and break if stop button is clicked try { var curFld = FldDatas[i]; if (curFld.GetIsMeasureComplete()) { continue; } if (curFld.Enable == false) { continue; } if (IsPaused()) {// measure stopped pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.PAUSED); // 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); } SetSEMExteralOff(); // update thread measure status class, let the main thread know that this sample measurement stopped ST_MSTMsg MsgSmpStop = new ST_MSTMsg(m_Sample); MsgSmpStop.InitSamplePausedMsg(); m_pMsrThread.SendMessageToMeasureGUI(MsgSmpStop); while (IsPaused()) { Thread.Sleep(300); } } 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); } break; } // check if sample measurement completes COTSImgScanPrm pScanParam = m_Sample.GetMsrParams().GetImageScanParam(); if (IsSampleOver(pScanParam)) { pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED); pStatus.ComputeTime(OTS_MSR_TIME_TYPE.COMPLT); break; } var BCregulater = m_pMsrThread.BCregulater; if (BCregulater.checkPeriodTime()) { BCregulater.DoBrightnessContrastAdjust(); } // get a field center System.Drawing.PointF poiFieldCentre = curFld.GetOTSPosition(); // update thread measure status class, let the main thread know that starts a new field ST_MSTMsg MsgFieldStart = new ST_MSTMsg(m_Sample, curFld); MsgFieldStart.InitFieldStartMsg(); m_pMsrThread.SendMessageToMeasureGUI(MsgFieldStart); int fldNo = curFld.GetId(); 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 BSE image."); pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED); return; } curFld.SetBSEImage(pBSEImg); //BSEData ST_MSTMsg MsgFieldBSE = new ST_MSTMsg(m_Sample, curFld); MsgFieldBSE.InitFieldBSEImageMsg(); m_pMsrThread.SendMessageToMeasureGUI(MsgFieldBSE); log.Info("Acquire BSE image success! Processing image..."); // image process FieldImageProcess(curFld); MsgFieldBSE.InitFieldBSEAnalysisPartsDataMsg(); m_pMsrThread.SendMessageToMeasureGUI(MsgFieldBSE); if (m_ifAquireClearParticleImage) { var listAnalysisParts = curFld.GetListAnalysisParticles(); foreach (var p in listAnalysisParts) { Rectangle r = (Rectangle)p.GetParticleRect(); var img = m_ScanHardwareMgr.AcquireRectangleBSEImage(r); if (img != null) { curFld.particleImages.Add(img); } } } COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam(); if (pXRayParam.GetUsingXray() == true) { foreach (var p in curFld.GetListAnalysisParticles()) { p.SetIsXrayParticle(true); } try { CollectParticlesXrayData(curFld); } catch (Exception e) { log.Error(e.Message); } } m_Sample.GetMsrStatus().SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED); curFld.SetIsMeasureComplete(true); log.Info("Begin to classify particles! particle num:" + curFld.GetListAnalysisParticles().Count); try { ClassifyFieldParticles(curFld); } catch (Exception e) { log.Error(e.Message); } MsgFieldBSE.InitFieldSTDColoredPartsDataMsg(); m_pMsrThread.SendMessageToMeasureGUI(MsgFieldBSE); //start db save StartSaveFileThread(ref curFld); // record pStatus.AddCompletedFieldCenter(curFld.GetOTSPosition()); pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED); SendFieldParticlesInfoToGUI(curFld, m_Sample.GetMsrStatus()); } catch (Exception e) { log.Error(e.Message); } } while (bSaveThreadWorking)//wait untill all the field data has been saved. { Thread.Sleep(1000); log.Warn("db saving!"); } TheLastWorkOfSampleMeasure(); } catch (Exception e) { log.Error(e.Message); } finally { SetSEMExteralOff(); } } public void TheLastWorkOfSampleMeasure() { COTSSample theSample = m_Sample; var pStatus = theSample.GetMsrStatus(); 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(m_Sample); MsgSmplEnd.InitSampleCompleteMsg(); m_pMsrThread.SendMessageToMeasureGUI(MsgSmplEnd); } public bool DoMEasureForReMeasure() { return true; } public virtual void FieldImageProcess(COTSField curFldData) { PointF fldCenter = curFldData.GetOTSPosition(); CSEMStageData a_pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData(); PointF semPos = new Point(); a_pCSEMStageData.ConvertOTSToSEMCoord(fldCenter, ref semPos); curFldData.SetSemPos(semPos); //first step:remove background of the bse image and compound all the finded particles. CSampleParam pMsrParam = m_Sample.GetMsrParams(); COTSImageProcParam pImgProcessParam = pMsrParam.GetImageProcessParam(); log.Info("Begin to process image and get all particles!"); //according to the ECD scope,filter out the effective particles,remove the noise. curFldData.GetOriginalParticles(m_Sample.GetMsrParams(), m_Sample.CalculatePixelSize()); if (curFldData.Sample.GetMsrParams().GetImageProcessParam().GetBGRemoveType() == OTS_BGREMOVE_TYPE.MATRIX) { curFldData.SetListAnalysisParticles(curFldData.GetAllParticles()); } else { log.Info("Begin to filter particles!"); curFldData.FilterParticles(m_Sample.GetMsrParams().GetXRayParam());//filter according to the xraylimit and outermost border log.Info("Begin to Calculate the image property of every particle!"); var analysisparts = curFldData.GetListAnalysisParticles(); curFldData.CalParticleImageProp(analysisparts);//calculate particle image property such as feret diameter, DMAX etc. curFldData.SelectParticlesAccordingImgProp(pImgProcessParam); var overlap = pImgProcessParam.GetOverlapParam(); if (overlap > 0) { try { curFldData.RemoveDuplicateOverlapParticles(overlap); } catch (Exception e) { log.Error(e.Message); } } } curFldData.CalculateParticleAbsolutPos(m_pMsrThread.GetProjResultData().GetSEMStageData()); curFldData.InitParticles(pImgProcessParam); return ; } public virtual void CollectParticlesXrayData(COTSField curFldData) { var allParts = curFldData.GetListXrayParticles(); var smallparts = new List(); var bigparts = new List(); double quantifyThreshold = m_Sample.GetMsrParams().GetXRayParam().GetFeatureModeMinSize(); foreach (var part in allParts) { double equalCircleDiameter = Math.Sqrt(part.GetActualArea() / 3.14159) * 2f; if (equalCircleDiameter < quantifyThreshold) { smallparts.Add(part); } else { bigparts.Add(part); } } log.Info("SmallQuantifyParts (<" + quantifyThreshold.ToString("f2") + "): " + smallparts.Count); log.Info("BigQuantifyParts (>=" + quantifyThreshold.ToString("f2") + "): " + bigparts.Count); curFldData.CreateXrayList(smallparts); curFldData.CreateXrayList(bigparts); // get x-ray parameters COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam(); var workmode = pXRayParam.GetScanMode(); if (workmode == OTS_X_RAY_SCAN_MODE.PointMode) { uint nXRayAQTime; if (bigparts.Count > 0) { nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime(); log.Info("Begin to collect xraydata:" + bigparts.Count +"(" +nXRayAQTime.ToString()+") on " + workmode.ToString()); m_EDSController.GetXRayByParts(bigparts, nXRayAQTime, true); } if (smallparts.Count > 0) { Thread.Sleep(1000);//add delay here,or else the eds system will halt. nXRayAQTime = (uint)pXRayParam.GetSmallPartXrayTime(); log.Info("Begin to collect xraydata:" + smallparts.Count + "(" + nXRayAQTime.ToString() + ") on " + workmode.ToString()); m_EDSController.GetXRayByParts(smallparts, nXRayAQTime, true); } } else if (workmode == OTS_X_RAY_SCAN_MODE.FeatureMode) { uint nXRayAQTime; if (bigparts.Count > 0) { log.Info("Begin to collect xraydata:" + bigparts.Count + " on " + OTS_X_RAY_SCAN_MODE.FeatureMode.ToString()); nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime(); m_EDSController.GetXRayByFeatures(bigparts, nXRayAQTime, true); } if (smallparts.Count > 0) { Thread.Sleep(1000); log.Info("Begin to collect xraydata:" + smallparts.Count + " on " + OTS_X_RAY_SCAN_MODE.PointMode.ToString()); nXRayAQTime = (uint)pXRayParam.GetSmallPartXrayTime(); m_EDSController.GetXRayByParts(smallparts, nXRayAQTime, true); } } else if (workmode == OTS_X_RAY_SCAN_MODE.ExpandMode) { uint nXRayAQTime; if (bigparts.Count > 0) { log.Info("Begin to collect xraydata:" + bigparts.Count + " on " + OTS_X_RAY_SCAN_MODE.FeatureMode.ToString()); nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime(); m_EDSController.GetXRayByExpandFeatures(bigparts, nXRayAQTime, true); } if (smallparts.Count > 0) { Thread.Sleep(500); log.Info("Begin to collect xraydata:" + smallparts.Count + " on " + OTS_X_RAY_SCAN_MODE.PointMode.ToString()); nXRayAQTime = (uint)pXRayParam.GetSmallPartXrayTime(); m_EDSController.GetXRayByParts(smallparts, nXRayAQTime, true); } } return; } public virtual void QuantifyParticlesXrayData(COTSField curFldData) { var parts = curFldData.GetListXrayParticles(); foreach (var p in parts) { m_EDSController.QuantifyXrayByPart(p); } } // Cumulate field data info public virtual bool CumulateFieldData( List listParticles, double a_nMeasuredArea) { // get measure result items of the sample CMsrResultItems pMsrResults = m_Sample.GetMsrResults(); // go through the particles list foreach (COTSParticleClr pParticle in listParticles) { // create a measure result item pMsrResults.CumulateMeasureResult(pParticle); } pMsrResults.CumulateMeasuredArea(a_nMeasuredArea); // cumulate ratio double dRatio = pMsrResults.GetTotalParticleArea(); dRatio = dRatio / pMsrResults.GetMeasuredArea(); pMsrResults.SetRatio(dRatio); m_Sample.SetMsrResults(pMsrResults); return true; } public bool SaveFieldData(COTSField fldData, string filedFileFoler) { string strFieldFileFolder = filedFileFoler; CBSEImageFileMgr pBSEImgFileMgr = new CBSEImageFileMgr(); pBSEImgFileMgr.SetBSEImg(fldData.GetBSEImage()); int nId = fldData.GetId(); string sFieldId; sFieldId = nId.ToString(); string strBSEFilePathname = strFieldFileFolder + "\\" + m_pSampleRstFile.SMPL_MSR_RESULT_FIELDS_BSE + sFieldId + pBSEImgFileMgr.BMP_IMG_FILE_EXT; if (!pBSEImgFileMgr.SaveIntoBitmap(strBSEFilePathname)) { log.Error("SaveFieldFiles: save BSE file failed."); return false; } if (fldData.particleImages.Count > 0) { for (int i=0;i> fldcmds = new List>(); fldcmds.Add(fldcmd); pDBFileMgr.ExecuteNonQueryBatch(ref fldcmds); //remomove the invalid particles var cmds = pDBFileMgr.GetSavingParticleDataToDBCmds(fldData.GetListAnalysisParticles(), fldData.GetOTSPosition()); pDBFileMgr.ExecuteNonQueryBatch(ref cmds); CPosXrayDBMgr PosXrayDBMgr = pDBFileMgr.GetPosXrayDBMgr(); var listAnalysisPosXray = new List(); foreach (var p in fldData.GetListXrayParticles()) { listAnalysisPosXray.Add(p.GetXray()); } var cmds1 = PosXrayDBMgr.GetSavingXrayCmds(listAnalysisPosXray, true); pDBFileMgr.ExecuteNonQueryBatch(ref cmds1); return true; } protected void SaveFieldMgrData() { while (bSaveThreadWorking) { while (fieldQueue.Count() > 0) { COTSField f = fieldQueue.Dequeue(); //save to disk first ,then pop . if the size is 0,then we know all the saving work is done. log.Info("Begin to save particles data! particle num:" + f.GetListAnalysisParticles().Count); SaveFieldData(f, m_pSampleRstFile.GetFieldFileSubFolderStr()); } if (fieldQueue.Count() == 0) { bSaveThreadWorking = false; //must set this flag,so the main thread can know this thread has exited. log.Warn("finished batch saving"); return; } } return; } private void SendFieldParticlesInfoToGUI(COTSField curFld,CMsrSampleStatus pStatus) { double measuredArea = 0; // this area should be the field area var a_pBSEImg = curFld.GetBSEImage(); double dPixelSize = curFld.GetPixelSize(); measuredArea = a_pBSEImg.GetHeight() * a_pBSEImg.GetWidth() * dPixelSize * dPixelSize; //Get measured area CumulateFieldData(curFld.GetListAnalysisParticles(), measuredArea); log.Info("Send field data to screen!"); ST_MSTMsg MsgFieldEnd = new ST_MSTMsg(m_Sample,curFld); MsgFieldEnd.InitFieldDataMsg(); m_pMsrThread.SendMessageToMeasureGUI(MsgFieldEnd); } protected void StartSaveFileThread(ref COTSField a_pFieldMgr) { fieldQueue.Enqueue(a_pFieldMgr); if (fieldQueue.Count() > 0) //if there's data in the queue and the previous thread has finished then start a new thread. { if (bSaveThreadWorking == false) { bSaveThreadWorking = true; m_thread_ptr = new System.Threading.Thread(this.SaveFieldMgrData);//m_thread_ptr = shared_ptr(new thread(&CSmplMeasureInc::SaveFieldMgrData, this)); m_thread_ptr.IsBackground = true; m_thread_ptr.Start(); } } } } }