using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using OTSCLRINTERFACE; using OTSDataType; using OTSModelSharp.Measure.OTSCleanliness; using OTSModelSharp.ServiceCenter; using OTSModelSharp.ServiceInterface; using static OTSDataType.otsdataconst; namespace OTSModelSharp { class CSmplMeasureCleanliness : CSmplMeasure { public CSmplMeasureCleanliness(string a_strWorkingFolder, COTSSample a_pSample):base(a_strWorkingFolder,a_pSample) { SetWorkingFolder(a_strWorkingFolder); SetSample(a_pSample); m_classifyEngine = new CClassifyEngine(); } // field image process public override bool FieldImageProcess(Point fldCenter, CBSEImgClr a_BSEImg) { int nNewFieldId; nNewFieldId = m_pSampleRstFile.GetIdForANewField(); //first step:remove background of the bse image and compound all the finded particles. curFldData = new CFieldDataClean( a_BSEImg,m_Sample.CalculatePixelSize()); CFieldDataClean curFldDataCln =( CFieldDataClean) curFldData; curFldData.SetId(nNewFieldId); curFldData.SetPosition(fldCenter); GetOriginalParticles(); // second step :filter the finded particles. FilterParticles((CFieldDataClean)curFldData); CalculateParticlePos(); COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam(); //collect xray data. if (pXRayParam.GetUsingXray() == true) { Thread.Sleep(100); CollectParticlesXrayData((CFieldDataClean)curFldData); Thread.Sleep(100); } //special treatment. //ParticleSpecialTreatment(); log.Info("Begin to Calculate the image property of every particle!"); var analysisparts = curFldDataCln.ListBigParticles; curFldData.CalParticleImageProp(analysisparts);//calculate particle image property such as feret diameter, DMAX etc. ClassifyFieldParticles(); // save field files m_Sample.GetMsrStatus() .SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED); StartSaveFileThread(curFldData); return true; } public void CalculateParticlePos() { double dPixelSize = m_Sample.CalculatePixelSize(); CSEMStageData pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData(); foreach (var p in curFldData.ListAnalysisParticles) { Point fldOtsPos = new Point(curFldData.PoiPos.X, curFldData.PoiPos.Y); Point semPos = new Point(); pCSEMStageData.ConverOTSToSEMPoint(fldOtsPos, ref semPos); p.SetAbsolutPos(semPos); } } // save field data protected void SaveFieldMgrData() { while (bSaveThreadWorking) { while (fieldQueue.Count() > 0) { CFieldDataClean f = (CFieldDataClean) fieldQueue.Dequeue(); double pixelSize = m_Sample.CalculatePixelSize(); //save to disk first ,then pop . if the size is 0,then we know all the saving work is done. SaveFieldFiles(f,m_pSampleRstFile.GetFieldFileSubFolderStr()); } if (fieldQueue.Count() == 0) { bSaveThreadWorking = false; //must set this flag,so the main thread can know this thread has exited. return; } } return; } protected void StartSaveFileThread(COTSFieldData 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.Start();//m_thread_ptr->detach(); } } } public void FilterParticles(CFieldDataClean fld) { // 1)remove over sized particles, too small particles and get a analysis particles list double dPixelSize = m_Sample.CalculatePixelSize(); CSampleParam pMsrParam = m_Sample.GetMsrParams(); COTSImageProcParam pImgProcessParam = pMsrParam.GetImageProcessParam(); curFldData.FilterParticles(pImgProcessParam, dPixelSize); if (curFldData.NoAnalysisParticle()) { log.Warn("There's no analysis particles!"); } //2) according to the quantify threshold size value saperate the analysis particles into two group :the bigparticles and the smallparticles. int quantifyThreshold = m_Sample.GetMsrParams().GetXRayParam().GetQuantifyMinSize(); var smallparts = fld.ListSmallParticles; var bigparts = fld.ListBigParticles; foreach (var part in curFldData.ListAnalysisParticles) { double equalCircleDiameter = Math.Sqrt(part.GetArea() / 3.14159) * 2f; if (equalCircleDiameter < quantifyThreshold) { smallparts.Add(part); } else { bigparts.Add(part); } } fld.ListSmallParticles = smallparts; fld.ListBigParticles = bigparts; //fld.SmallParticlePercentage=percentage; log.Info("SmallQuantifyParts (<" + quantifyThreshold.ToString("f2") + "): " + smallparts.Count); log.Info("BigQuantifyParts (>=" + quantifyThreshold.ToString("f2")+ "): " + bigparts.Count); return ; } public void CollectParticlesXrayData(CFieldDataClean fld) { // get x-ray parameters COTSXRayParam pXRayParam = m_Sample.GetMsrParams ().GetXRayParam(); // calculate search x-ray acquire time uint nXRayAQTime; var smallparts = fld.ListSmallParticles; var bigparts = fld.ListBigParticles; var pStatus = m_Sample.GetMsrStatus(); //// particle x-ray analysis ////============================================= curFldData.CreateXrayList(bigparts); // big particle using the full xray strategy. curFldData.CreateXrayList(smallparts); //small particle using the fast xray strategy // get x-ray list (analysis) by particle features nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime(); m_EDSHardwareMgr.GetXRayByFeatures(bigparts, nXRayAQTime, true); nXRayAQTime = (uint)pXRayParam.GetFastXrayTime(); // get x-ray list (analysis) by points m_EDSHardwareMgr.GetXRayByPoints(smallparts, nXRayAQTime, true); return ; } public void ParticleSpecialTreatment(CFieldDataClean fld) { //we adopt such a strategy here:if some particles satisfy the predefined condition then we go through the second collecting with max EDS time,so that we got a more acurate result. Dictionary mapPartXray = new Dictionary(); //std.map mapPartXray = new std.map(); double edsTime = 0; //to store the EDSTime returned from the engine. var bigparts = fld.ListBigParticles; var m_ClassifyEngine = new CClassifyEngine(); for (int i = 0; i < bigparts.Count(); i++) { var engine = m_ClassifyEngine.GetParticleEngine(m_Sample.GetMsrParams().GetSTDName()); var p = bigparts[i]; // there will be very less particle satisfied the condition ,so we use only one MaxEDS time,though we set MaxEDSTime for every rule separately .Here we store the last one. //if the particle satisfied the MaxEDS condition then we go through the second colleting.Here we record the particle and the EDSTime and the corresponding xray position. edsTime = engine.IfNeedMaxEDS(p); if (edsTime > 0) { mapPartXray[p] = i; } } List partsMax = new List(); if (mapPartXray.Count() > 0) { foreach (var p in mapPartXray) { partsMax.Add(p.Key); } List maxEDSXrays = new List(); m_EDSHardwareMgr.GetXRayByFeatures(partsMax, edsTime, true); } } public override void ClassifyFieldParticles() { try { CFieldDataClean curFldDataCln = (CFieldDataClean)curFldData; string libname = m_Sample.GetMsrParams().GetSTDName(); if (libname != "NoSTDDB") { log.Info("Begin to classify big particles!Using " + libname); var bigparts = curFldDataCln.ListBigParticles; ClassifyQuantifyParticles(bigparts,libname); var smallParts = curFldDataCln.ListSmallParticles; ClassifySmallParticles(smallParts, libname); } } catch (Exception e) { log.Info("calcu the particle image property or classify failed. "+e.Message); } } public override void ClassifyMergedParticles(List mergedParts) { try { try { string libname = m_Sample.GetMsrParams().GetSTDName(); if (libname != "NoSTDDB") { log.Info("Begin to classify big particles!Using " + libname); var bigparts = mergedParts; ClassifyQuantifyParticles(bigparts, libname); } } catch (Exception e) { log.Info("calcu the particle image property or classify failed. " + e.Message); } } catch (Exception e) { log.Info(" classify failed. " + e.Message); } } public void SaveFieldParticlesData() { StartSaveFileThread(curFldData); } public void GetOriginalParticles() { // measure status CMsrSampleStatus pStatus = m_Sample.GetMsrStatus(); // get image process parameter CSampleParam pMsrParam = m_Sample.GetMsrParams(); COTSImageProcParam pImgProcessParam = pMsrParam.GetImageProcessParam(); // remove BES image background curFldData.RemoveBSEImageBG(pImgProcessParam); // check if this is an empty image if (curFldData.NoParticle()) { // empty fields log.Info("ImageProcess: empty field."); //return false; } return ; } public bool ClassifyQuantifyParticles(List a_listAnalysisParticles, string libname)// classify particles { int nSize = (int)a_listAnalysisParticles.Count(); // go through all analysis particles for (int i = 0; i < nSize; ++i) { COTSParticleClr pParticle = a_listAnalysisParticles[i]; //CPosXrayClr pXray = a_listAnalysisParticles[i].GetXray(); // CLEEngine engine = GetParticleEngine(libname.GetBuffer()); IClassifyEngine engine = m_classifyEngine.GetParticleEngine(libname); if (!engine.Classify(pParticle)) { // invalid x-ray pointer. log.Info("ClassifyParticle: can't identify the particle as any inclusion."); return false; } } // ok, return TRUE return true; } public bool ClassifySmallParticles(List smallparts, string libname) { List a_listAnalysisParticles = smallparts; int nSize = (int)a_listAnalysisParticles.Count(); // go through all analysis particles for (int i = 0; i < nSize; ++i) { COTSParticleClr pParticle = a_listAnalysisParticles[i]; IClassifyEngine engine = m_classifyEngine.GetCurveCompareEngine(libname); if (!engine.Classify(pParticle)) { log.Info("ClassifyParticle: can't identify the particle as any inclusion."); return false; } } return true; } public bool SaveFieldFiles(CFieldDataClean 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.Info("SaveFieldFiles: save BSE file failed."); return false; } // IncA Data list CIncAFileMgr pDBFileMgr = m_pSampleRstFile.DBFileMgr; //pDBFileMgr.BeginTransaction(); pDBFileMgr.SaveStatusDataToDB(); var fldDB = pDBFileMgr.GetFieldDB(); fldDB.SaveAField(fldData.GetId(), fldData.GetPosition()); if (!pDBFileMgr.SaveIncADataToDB(fldData.ListAnalysisParticles, fldData.GetPosition())) { log.Info("SaveFieldFiles: save inclusion file failed."); return false; } //save the xray data and element data. CPosXrayDBMgr PosXrayDBMgr = pDBFileMgr.GetPosXrayDBMgr(); var m_listAnalysisPosXray = new List(); foreach (var p in fldData. ListAnalysisParticles) { m_listAnalysisPosXray.Add(p.GetXray()); } if (!PosXrayDBMgr.SaveXray(m_listAnalysisPosXray, true)) { log.Info("SaveFieldFiles: save analysis x-ray failed."); return false; } //save the small particle info CSmallParticleInfoDB smallPartDB = pDBFileMgr.GetSmallParticleInfoDB(); Dictionary> mapSmallParts = new Dictionary>(); foreach (COTSParticleClr smallP in fldData.ListSmallParticles) { if (mapSmallParts.ContainsKey((int)smallP.GetType())) { mapSmallParts[(int)smallP.GetType()].Add(smallP); } else { var plist = new List(); plist.Add(smallP); mapSmallParts.Add((int)smallP.GetType(), plist); } } List smallparts = new List(); foreach (KeyValuePair> particles in mapSmallParts) { CSmallParticleInfo partInfo = new CSmallParticleInfo(); partInfo.FieldId = particles.Value[0].GetFieldId(); partInfo.AveGray = particles.Value[0].GetAveGray(); partInfo.Quantity = (int)(particles.Value.Count / fldData.SmallParticlePercentage); partInfo.TypeId = particles.Key; partInfo.TypeColor = particles.Value[0].GetTypeColor(); partInfo.TypeName = particles.Value[0].GetTypeName(); double area = 0; foreach (var p in particles.Value) { area += p.GetArea(); } //partInfo.Area = Convert.ToInt32(area / f.SmallParticlePercentage); partInfo.Area =(int) area ; smallparts.Add(partInfo); } foreach (CSmallParticleInfo smallp in smallparts) { smallPartDB.SaveAKindOfSmallParticle(smallp, new CPosXrayClr(), new System.Drawing.Point(0, 0)); } //pDBFileMgr.CommitTransaction(); return true; } } }