CSmplMeasure.cs 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using OTSModelSharp.ServiceCenter;
  5. using static OTSDataType.otsdataconst;
  6. using OTSDataType;
  7. using System.Drawing;
  8. using System.Threading;
  9. using OTSCLRINTERFACE;
  10. using OTSMeasureApp._1_OTSMeasure.Measure._3_MeasureFlow;
  11. using OTSMeasureApp._0_OTSModel.OTSDataType;
  12. namespace OTSModelSharp
  13. {
  14. public class CSmplMeasure
  15. {
  16. protected static NLog.Logger log ;
  17. protected bool bSaveThreadWorking;
  18. protected System.Threading.Thread m_thread_ptr;
  19. protected COTSSample m_Sample;
  20. protected CMeasure m_pMsrThread;
  21. string m_strWorkingFolder;
  22. protected CSmplMsrResult m_pSampleRstFile;
  23. internal ISemController m_SemHardwareMgr;
  24. internal IScanController m_ScanHardwareMgr;
  25. internal IEDSController m_EDSController;
  26. protected Queue<COTSField> fieldQueue=new Queue<COTSField>();
  27. protected IClassifyEngine m_classifyEngine;
  28. private bool m_ifAquireClearParticleImage=false;
  29. public CSmplMeasure( string a_strWorkingFolder, COTSSample a_pSample)
  30. {
  31. m_Sample = a_pSample;
  32. log = NLog.LogManager.GetCurrentClassLogger();
  33. var expC = m_Sample.GetMsrParams().GetXRayParam().GetAnalyExpCount();
  34. var imgwidth = m_Sample.GetMsrParams().GetImageScanParam().GetImageResolutionSize().cx;
  35. var imgheight = m_Sample.GetMsrParams().GetImageScanParam().GetImageResolutionSize().cy;
  36. m_strWorkingFolder = a_strWorkingFolder;
  37. m_pSampleRstFile = new CSmplMsrResult( a_strWorkingFolder, a_pSample);
  38. m_SemHardwareMgr = SemController.GetSEMController();
  39. m_ScanHardwareMgr = ScanController.GetScanController();
  40. var ifautoid = m_Sample.GetMsrParams().GetXRayParam().IfAutoId;
  41. var knownelements = m_Sample.GetMsrParams().GetXRayParam().AnalysisElements;
  42. m_EDSController = EDSController.GetEDSController(imgwidth,imgheight,expC,ifautoid,knownelements);
  43. m_ifAquireClearParticleImage = FileHelper.GetIfAquireClearParticleImage();
  44. }
  45. public void SetSample(COTSSample a_pSample)
  46. {
  47. m_Sample = a_pSample;
  48. m_pSampleRstFile.SetSample(a_pSample);
  49. }
  50. public COTSSample GetSample() { return m_Sample; }
  51. public void SetMsrThread(CMeasure mt)
  52. {
  53. m_pMsrThread = mt;
  54. }
  55. bool SetSEMDataMrs(CSEMFieldData pSEMDataMsr)
  56. {
  57. //var pSEMDataMsr = sample.GetSEMDataMsr();
  58. double dMag = pSEMDataMsr.GetMagnification();
  59. double dWorkDis = pSEMDataMsr.GetWorkingDistance();
  60. double bri=pSEMDataMsr.Brightness;
  61. double contra = pSEMDataMsr.Contrast;
  62. try
  63. {
  64. var pSEMCtrl = m_pMsrThread.GetSEMController();
  65. pSEMCtrl.SetMagnification(dMag);
  66. pSEMCtrl.SetWorkingDistance(dWorkDis);
  67. //pSEMCtrl.SetSemBrightness(bri);
  68. //pSEMCtrl.SetSemContrast(contra);
  69. log.Warn("set magnification " + dMag);
  70. log.Warn("set wd "+ dWorkDis);
  71. //log.Warn("set brightness "+bri);
  72. //log.Warn("set contrast "+contra);
  73. }
  74. catch (Exception e)
  75. {
  76. log.Error(e.Message);
  77. }
  78. return true;
  79. }
  80. // set SEM external off
  81. bool SetSEMExteralOff()
  82. {
  83. var pSEMCtrlPtr = m_SemHardwareMgr;
  84. log.Warn("Set SEM Exteral Off!");
  85. pSEMCtrlPtr.SetScanExternal(false);
  86. return true;
  87. }
  88. internal bool InitScanControllerBSEParam()
  89. {
  90. // get scan controller
  91. var pScanController = m_ScanHardwareMgr;
  92. // scan parameters
  93. var pMsrParam = m_Sample.GetMsrParams();
  94. var pImgScanParam = pMsrParam.GetImageScanParam();
  95. // get image size
  96. var nImageSizeId = pImgScanParam.GetImageResulotion();
  97. int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId;
  98. Size sizePixelImage = RESOLUTION_VALUE[nResulotionId];
  99. // get dwell time
  100. OTS_IMAGE_SCANSPEED_OPTIONS nDwellTime = pImgScanParam.GetScanImageSpeed();
  101. // convert dwell time to bruker dwell time
  102. DwellTimeLevel DwellTimeId;
  103. switch (nDwellTime)
  104. {
  105. case OTS_IMAGE_SCANSPEED_OPTIONS.low:
  106. DwellTimeId = DwellTimeLevel.Low;
  107. break;
  108. case OTS_IMAGE_SCANSPEED_OPTIONS.meddium:
  109. DwellTimeId = DwellTimeLevel.Medium;
  110. break;
  111. case OTS_IMAGE_SCANSPEED_OPTIONS.high:
  112. DwellTimeId = DwellTimeLevel.High;
  113. break;
  114. default:
  115. DwellTimeId = DwellTimeLevel.Low;
  116. break;
  117. }
  118. if (!pScanController.Init())
  119. {
  120. log.Error("InitScanControllerBSEParam: failed to get scan control.");
  121. return false;
  122. }
  123. // set dwell time
  124. if (!pScanController.SetDwellTime(DwellTimeId))
  125. {
  126. return false;
  127. }
  128. // set image size
  129. if (!pScanController.SetImageSize(sizePixelImage.Width,sizePixelImage.Height))
  130. {
  131. // failed to set dwell time
  132. log.Error("InitScanControllerBSEParam: failed to set dwell time (%d).", sizePixelImage.Height);
  133. return false;
  134. }
  135. return true;
  136. }
  137. public void SetWorkingFolder(String a_strWorkingFolder)
  138. {
  139. // add "\\" at the string end if it is not "\\"
  140. if (a_strWorkingFolder.PadRight(1)!="\\")
  141. {
  142. a_strWorkingFolder += "\\";
  143. }
  144. m_strWorkingFolder = a_strWorkingFolder + m_Sample.GetName() + "\\";
  145. }
  146. protected bool IsAborted()
  147. {
  148. return m_pMsrThread.IsMeasureStopped();
  149. }
  150. protected bool IsPaused()
  151. {
  152. var statu = m_pMsrThread.GetMsrThreadStatusobj();
  153. if (statu.GetStatus() == OTS_MSR_THREAD_STATUS.PAUSED)
  154. {
  155. return true;
  156. }
  157. else
  158. {
  159. return false;
  160. }
  161. }
  162. bool IsSampleOver(COTSImgScanPrm a_pScanParam)
  163. {
  164. string sStopMode = a_pScanParam.GetStopMode();
  165. int nStopField = a_pScanParam.GetStopParamFields();
  166. // completed fields number
  167. CMsrSampleStatus pMsrSampleStatus = m_Sample.GetMsrStatus();
  168. int nCompeltedField = pMsrSampleStatus.GetCompletedFields();
  169. CMsrResultItems pMsrResults = m_Sample.GetMsrResults();
  170. List<CMsrResultItem> listMsrResult = pMsrResults.GetResultItems();
  171. int nNumParticle = 0;
  172. foreach (var pResult in listMsrResult)
  173. {
  174. if (pResult.GetTypeId() > (int)OTS_PARTICLE_TYPE.NOT_IDENTIFIED)//summarize the number of the identified particle in this condition
  175. {
  176. nNumParticle += (int)pResult.GetNumber();
  177. }
  178. }
  179. TimeSpan timeSpan = pMsrSampleStatus.GetUsedTime();
  180. int nDay = timeSpan.Days;
  181. int nHour = timeSpan.Hours;
  182. int nMin = timeSpan.Minutes;
  183. int nSec = timeSpan.Seconds;
  184. int nUsedTime = nSec + nMin * 60 + nHour * 3600 + nDay * 86400;
  185. int NMeasArea = (int)pMsrResults.GetMeasuredArea();
  186. int nParticlAim = a_pScanParam.GetStopParamParticles();
  187. int nMeasTimeAim = a_pScanParam.GetStopParamMeasTime();
  188. int NMeasAreaAim = a_pScanParam.GetStopParamArea()*1000000 ;
  189. bool bRet = false;
  190. string[] str = sStopMode.Replace(" ", "").Split('+');
  191. for(int i=0;i< str.Length;i++)
  192. {
  193. switch (int.Parse(str[i].Split(':')[0])-1)
  194. {
  195. case (int)OTS_MEASURE_STOP_MODE.CoverMode:
  196. // completed fields number
  197. if (nCompeltedField == m_Sample.GetFieldsData().Count)
  198. {
  199. bRet = true;
  200. }
  201. break;
  202. case (int)OTS_MEASURE_STOP_MODE.FieldMode:
  203. if (nCompeltedField >= nStopField)
  204. {
  205. bRet = true;
  206. }
  207. break;
  208. case (int)OTS_MEASURE_STOP_MODE.ParticleMode:
  209. if (nNumParticle >= nParticlAim)
  210. {
  211. bRet = true;
  212. }
  213. break;
  214. case (int)OTS_MEASURE_STOP_MODE.TimeMode:
  215. if (nUsedTime >= nMeasTimeAim)
  216. {
  217. bRet = true;
  218. }
  219. break;
  220. case (int)OTS_MEASURE_STOP_MODE.AreaMode:
  221. if (NMeasArea >= NMeasAreaAim)
  222. {
  223. bRet = true;
  224. }
  225. break;
  226. default:
  227. break;
  228. }
  229. }
  230. return bRet;
  231. }
  232. // move SEM to the point
  233. internal bool MoveSEMToPoint(System.Drawing.PointF a_poi)
  234. {
  235. // get SEM controller
  236. var pSEMController = m_SemHardwareMgr;
  237. PointF a_SEMpt = new Point();
  238. CSEMStageData a_pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData();
  239. int hardWareDelay = a_pCSEMStageData.GetHardWareDelay();
  240. if (!a_pCSEMStageData.ConvertOTSToSEMCoord(a_poi, ref a_SEMpt))
  241. {
  242. return false;
  243. }
  244. log.Info("Begin to move SEM stage to OTScoord:" + a_poi.X + "," + a_poi.Y);
  245. log.Info("Begin to move SEM stage to " + a_SEMpt.X + "," + a_SEMpt.Y);
  246. // move SEM to the position (rotation 0)
  247. if (!pSEMController.MoveSEMToPoint(a_SEMpt.X, a_SEMpt.Y))
  248. {
  249. log.Error("MoveSEMToPoint: failed to call MoveSEMToPoint method.");
  250. return false;
  251. }
  252. CSampleParam pMsrParam = m_Sample.GetMsrParams();
  253. if (pMsrParam.SlopParam.IsUsingSlopParam)
  254. {
  255. double wd = pMsrParam.SlopParam.GetWD(a_SEMpt);
  256. double originWd = 0;
  257. pSEMController.GetWorkingDistance(ref originWd);
  258. if ((wd - originWd) > 2)
  259. {
  260. log.Warn("Working Distance is invalid,outof the moving scope(2cm) wd=" + wd.ToString("F2"));
  261. }
  262. else
  263. {
  264. Thread.Sleep(hardWareDelay);
  265. pSEMController.SetWorkingDistance(wd);
  266. log.Info("Set Working Distance to:" + wd.ToString("F2"));
  267. }
  268. }
  269. if (hardWareDelay > 0)
  270. {
  271. Thread.Sleep(hardWareDelay);
  272. }
  273. return true;
  274. }
  275. // Acquire a BSE image
  276. CBSEImgClr AcquireABSEImage()
  277. {
  278. // BSE image
  279. CBSEImgClr pBSEImage = null;
  280. // get scan controller
  281. var pScanController = m_ScanHardwareMgr;
  282. pBSEImage = pScanController.AcquireBSEImage();
  283. return pBSEImage;
  284. }
  285. public bool IsLowCounts(COTSParticleClr particle)
  286. {
  287. COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam();
  288. if (pXRayParam.GetUsingXray() == true)
  289. {
  290. var thecount = particle.GetXray().GetTotalCount();
  291. var expect = pXRayParam.GetAnalyExpCount();
  292. if (thecount < expect)
  293. {
  294. particle.SetType((int)OTS_PARTICLE_TYPE.LOW_COUNT);
  295. particle.SetClassifyId((int)OTS_PARTICLE_TYPE.LOW_COUNT);
  296. particle.SetTypeColor("#000000");
  297. particle.SetTypeName("LowCounts");
  298. return true;
  299. }
  300. }
  301. return false;
  302. }
  303. public virtual void ClassifyFieldParticles(COTSField curFldData)
  304. {
  305. return;
  306. }
  307. private bool GetSEMDataGnrFromHw(ref CSEMDataGnr SemDataGnr)
  308. {
  309. double kv = 0, brightness = 0, contrast = 0;
  310. var hw = SemController.GetSEMController();
  311. hw.GetSemHighTension(ref kv);
  312. hw.GetSemBrightness(ref brightness);
  313. hw.GetSemContrast(ref contrast);
  314. SemDataGnr.SetValue(kv, brightness, contrast);
  315. return true;
  316. }
  317. public void DoMeasureForOneSample()
  318. {
  319. try
  320. {
  321. // let the main thread to know that this sample measurement starts
  322. var pStatus = m_Sample.GetMsrStatus();
  323. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS);
  324. // set current time to current time
  325. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.START);
  326. // let main App know that the sample begin to measure
  327. ST_MSTMsg MsgSmpStart = new ST_MSTMsg(m_Sample);
  328. MsgSmpStart.InitSampleStartMsg();
  329. m_pMsrThread.SendMessageToMeasureGUI(MsgSmpStart);
  330. log.Info(m_Sample.GetName() + " Measurement started!");
  331. // get SEM controller to set magnification and working distance
  332. if (!SetSEMDataMrs(m_Sample.GetSEMDataMsr()))
  333. {
  334. log.Error("DoMeasure: fail to set SEM data.");
  335. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  336. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  337. return;
  338. }
  339. // set the BSE scan param
  340. if (!InitScanControllerBSEParam())
  341. {
  342. log.Error("DoMeasure: fail to set BSE param.");
  343. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  344. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  345. return;
  346. }
  347. var pSEMDataGnr = new CSEMDataGnr();
  348. log.Info("Get current Kv, Brightness and Contrast!");
  349. GetSEMDataGnrFromHw(ref pSEMDataGnr);
  350. m_pSampleRstFile.SetSEMDataGnr(pSEMDataGnr);
  351. // record SEM data
  352. COTSMsrPrjResultData pProjMgrFile = m_pMsrThread.GetProjResultData();
  353. CSEMStageData pSEMStageData = pProjMgrFile.GetSEMStageData();
  354. m_pSampleRstFile.SetSEMStageData(pSEMStageData);
  355. CSampleHolder pSampleStage = pProjMgrFile.GetStageHolder();
  356. m_pSampleRstFile.SetSEMStage(pSampleStage);
  357. //-----save the static measure result file data into xml file and the dynamic data of every field will be saved into sqlite database
  358. log.Info("Create result file!");
  359. if (!m_pSampleRstFile.CreateResultFiles())
  360. {// failed to call measure result file Save method
  361. log.Error("DoMeasure: failed to call measure result file Save method.");
  362. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  363. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  364. return;
  365. }
  366. //------
  367. var FldDatas = m_Sample.GetFieldsData();
  368. for (int i = 0; i < FldDatas.Count; ++i)
  369. {// check and break if stop button is clicked
  370. try
  371. {
  372. var curFld = FldDatas[i];
  373. if (curFld.GetIsMeasureComplete())
  374. {
  375. continue;
  376. }
  377. if (curFld.Enable == false)
  378. {
  379. continue;
  380. }
  381. if (IsPaused())
  382. {// measure stopped
  383. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.PAUSED);
  384. // record end time
  385. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  386. //must wait for the saving data thread finished,or we'll get null pointer exception when we stop the measure process.
  387. while (fieldQueue.Count() > 0)
  388. {
  389. Thread.Sleep(100);
  390. }
  391. SetSEMExteralOff();
  392. // update thread measure status class, let the main thread know that this sample measurement stopped
  393. ST_MSTMsg MsgSmpStop = new ST_MSTMsg(m_Sample);
  394. MsgSmpStop.InitSamplePausedMsg();
  395. m_pMsrThread.SendMessageToMeasureGUI(MsgSmpStop);
  396. while (IsPaused())
  397. {
  398. Thread.Sleep(300);
  399. }
  400. }
  401. if (IsAborted())
  402. {// measure stopped
  403. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.STOPPED);
  404. // record end time
  405. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  406. //must wait for the saving data thread finished,or we'll get null pointer exception when we stop the measure process.
  407. while (fieldQueue.Count() > 0)
  408. {
  409. Thread.Sleep(100);
  410. }
  411. break;
  412. }
  413. // check if sample measurement completes
  414. COTSImgScanPrm pScanParam = m_Sample.GetMsrParams().GetImageScanParam();
  415. if (IsSampleOver(pScanParam))
  416. {
  417. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
  418. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.COMPLT);
  419. break;
  420. }
  421. var BCregulater = m_pMsrThread.BCregulater;
  422. if (BCregulater.checkPeriodTime())
  423. {
  424. BCregulater.DoBrightnessContrastAdjust();
  425. }
  426. // get a field center
  427. System.Drawing.PointF poiFieldCentre = curFld.GetOTSPosition();
  428. // update thread measure status class, let the main thread know that starts a new field
  429. ST_MSTMsg MsgFieldStart = new ST_MSTMsg(m_Sample, curFld);
  430. MsgFieldStart.InitFieldStartMsg();
  431. m_pMsrThread.SendMessageToMeasureGUI(MsgFieldStart);
  432. int fldNo = curFld.GetId();
  433. log.Warn("Current field:" + fldNo.ToString());
  434. // move SEM to the field center
  435. if (!MoveSEMToPoint(poiFieldCentre))
  436. {// failed to move SEM to the position
  437. log.Error("DoMeasure: failed to move SEM to the field centre point.");
  438. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  439. // record end time
  440. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  441. return;
  442. }
  443. log.Info("Begin to Acquire BSE image!");
  444. // take BSE image for the fields
  445. CBSEImgClr pBSEImg = AcquireABSEImage();
  446. // let the main thread to know that image process is completed
  447. if (pBSEImg == null)
  448. {
  449. log.Error("ImageProcess: can't get BSE image.");
  450. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  451. return;
  452. }
  453. curFld.SetBSEImage(pBSEImg);
  454. //BSEData
  455. ST_MSTMsg MsgFieldBSE = new ST_MSTMsg(m_Sample, curFld);
  456. MsgFieldBSE.InitFieldBSEImageMsg();
  457. m_pMsrThread.SendMessageToMeasureGUI(MsgFieldBSE);
  458. log.Info("Acquire BSE image success! Processing image...");
  459. // image process
  460. FieldImageProcess(curFld);
  461. MsgFieldBSE.InitFieldBSEAnalysisPartsDataMsg();
  462. m_pMsrThread.SendMessageToMeasureGUI(MsgFieldBSE);
  463. if (m_ifAquireClearParticleImage)
  464. {
  465. var listAnalysisParts = curFld.GetListAnalysisParticles();
  466. foreach (var p in listAnalysisParts)
  467. {
  468. Rectangle r = (Rectangle)p.GetParticleRect();
  469. var img = m_ScanHardwareMgr.AcquireRectangleBSEImage(r);
  470. if (img != null)
  471. {
  472. curFld.particleImages.Add(img);
  473. }
  474. }
  475. }
  476. COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam();
  477. if (pXRayParam.GetUsingXray() == true)
  478. {
  479. foreach (var p in curFld.GetListAnalysisParticles())
  480. {
  481. p.SetIsXrayParticle(true);
  482. }
  483. try
  484. {
  485. CollectParticlesXrayData(curFld);
  486. }
  487. catch (Exception e)
  488. {
  489. log.Error(e.Message);
  490. }
  491. }
  492. m_Sample.GetMsrStatus().SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
  493. curFld.SetIsMeasureComplete(true);
  494. log.Info("Begin to classify particles! particle num:" + curFld.GetListAnalysisParticles().Count);
  495. try
  496. {
  497. ClassifyFieldParticles(curFld);
  498. }
  499. catch (Exception e)
  500. {
  501. log.Error(e.Message);
  502. }
  503. MsgFieldBSE.InitFieldSTDColoredPartsDataMsg();
  504. m_pMsrThread.SendMessageToMeasureGUI(MsgFieldBSE);
  505. //start db save
  506. StartSaveFileThread(ref curFld);
  507. // record
  508. pStatus.AddCompletedFieldCenter(curFld.GetOTSPosition());
  509. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  510. SendFieldParticlesInfoToGUI(curFld, m_Sample.GetMsrStatus());
  511. }
  512. catch (Exception e)
  513. {
  514. log.Error(e.Message);
  515. }
  516. }
  517. while (bSaveThreadWorking)//wait untill all the field data has been saved.
  518. {
  519. Thread.Sleep(1000);
  520. log.Warn("db saving!");
  521. }
  522. TheLastWorkOfSampleMeasure();
  523. }
  524. catch (Exception e)
  525. {
  526. log.Error(e.Message);
  527. }
  528. finally
  529. {
  530. SetSEMExteralOff();
  531. }
  532. }
  533. public void TheLastWorkOfSampleMeasure()
  534. {
  535. COTSSample theSample = m_Sample;
  536. var pStatus = theSample.GetMsrStatus();
  537. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.COMPLT);
  538. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
  539. // let main thread to know that this sample measurement completes
  540. ST_MSTMsg MsgSmplEnd = new ST_MSTMsg(m_Sample);
  541. MsgSmplEnd.InitSampleCompleteMsg();
  542. m_pMsrThread.SendMessageToMeasureGUI(MsgSmplEnd);
  543. }
  544. public bool DoMEasureForReMeasure()
  545. {
  546. return true;
  547. }
  548. public virtual void FieldImageProcess(COTSField curFldData)
  549. {
  550. PointF fldCenter = curFldData.GetOTSPosition();
  551. CSEMStageData a_pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData();
  552. PointF semPos = new Point();
  553. a_pCSEMStageData.ConvertOTSToSEMCoord(fldCenter, ref semPos);
  554. curFldData.SetSemPos(semPos);
  555. //first step:remove background of the bse image and compound all the finded particles.
  556. CSampleParam pMsrParam = m_Sample.GetMsrParams();
  557. COTSImageProcParam pImgProcessParam = pMsrParam.GetImageProcessParam();
  558. log.Info("Begin to process image and get all particles!");
  559. //according to the ECD scope,filter out the effective particles,remove the noise.
  560. curFldData.GetOriginalParticles(m_Sample.GetMsrParams(), m_Sample.CalculatePixelSize());
  561. if (curFldData.Sample.GetMsrParams().GetImageProcessParam().GetBGRemoveType() == OTS_BGREMOVE_TYPE.MATRIX)
  562. {
  563. curFldData.SetListAnalysisParticles(curFldData.GetInitialParticles());
  564. }
  565. else if( curFldData.Sample.GetMsrParams().GetImageProcessParam().GetBGRemoveType() == OTS_BGREMOVE_TYPE.WaterShed)
  566. {
  567. List<COTSParticleClr> allsubRegions = new List<COTSParticleClr>();
  568. var parts = curFldData.GetInitialParticles();
  569. foreach (var p in parts)
  570. {
  571. if (p.GetSubParticles().Count>0)
  572. {
  573. var subparts = p.GetSubParticles();
  574. allsubRegions.AddRange(subparts);
  575. }
  576. else
  577. {
  578. allsubRegions.Add(p);
  579. }
  580. }
  581. curFldData.SetListAnalysisParticles(allsubRegions);
  582. curFldData.CalParticleImageProp(parts);//calculate particle image property such as feret diameter, DMAX etc.
  583. }
  584. else
  585. {
  586. log.Info("Begin to filter particles!");
  587. curFldData.FilterParticles(m_Sample.GetMsrParams().GetXRayParam());//filter according to the xraylimit
  588. log.Info("Begin to Calculate the image property of every particle!");
  589. var analysisparts = curFldData.GetListAnalysisParticles();
  590. curFldData.CalParticleImageProp(analysisparts);//calculate particle image property such as feret diameter, DMAX etc.
  591. curFldData.SelectParticlesAccordingImgProp(pImgProcessParam);
  592. var overlap = pImgProcessParam.GetOverlapParam();
  593. if (overlap > 0)
  594. {
  595. try
  596. {
  597. curFldData.RemoveDuplicateOverlapParticles(overlap);
  598. }
  599. catch (Exception e)
  600. {
  601. log.Error(e.Message);
  602. }
  603. }
  604. }
  605. curFldData.CalculateParticleAbsolutPos(m_pMsrThread.GetProjResultData().GetSEMStageData());
  606. curFldData.InitParticles(pImgProcessParam);
  607. return ;
  608. }
  609. public virtual void CollectParticlesXrayData(COTSField curFldData)
  610. {
  611. var allParts = curFldData.GetListXrayParticles();
  612. var smallparts = new List<COTSParticleClr>();
  613. var bigparts = new List<COTSParticleClr>();
  614. double quantifyThreshold = m_Sample.GetMsrParams().GetXRayParam().GetFeatureModeMinSize();
  615. foreach (var part in allParts)
  616. {
  617. double equalCircleDiameter = Math.Sqrt(part.GetActualArea() / 3.14159) * 2f;
  618. if (equalCircleDiameter < quantifyThreshold)
  619. {
  620. smallparts.Add(part);
  621. }
  622. else
  623. {
  624. bigparts.Add(part);
  625. }
  626. }
  627. log.Info("SmallQuantifyParts (<" + quantifyThreshold.ToString("f2") + "): " + smallparts.Count);
  628. log.Info("BigQuantifyParts (>=" + quantifyThreshold.ToString("f2") + "): " + bigparts.Count);
  629. curFldData.CreateXrayList(smallparts);
  630. curFldData.CreateXrayList(bigparts);
  631. // get x-ray parameters
  632. COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam();
  633. var workmode = pXRayParam.GetScanMode();
  634. if (workmode == OTS_X_RAY_SCAN_MODE.PointMode)
  635. {
  636. uint nXRayAQTime;
  637. if (bigparts.Count > 0)
  638. {
  639. nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime();
  640. log.Info("Begin to collect xraydata:" + bigparts.Count + "(" + nXRayAQTime.ToString() + ") on " + workmode.ToString());
  641. m_EDSController.GetXRayByParts(bigparts, nXRayAQTime, true);
  642. }
  643. if (smallparts.Count > 0)
  644. {
  645. Thread.Sleep(1000);//add delay here,or else the eds system will halt.
  646. nXRayAQTime = (uint)pXRayParam.GetSmallPartXrayTime();
  647. log.Info("Begin to collect xraydata:" + smallparts.Count + "(" + nXRayAQTime.ToString() + ") on " + workmode.ToString());
  648. m_EDSController.GetXRayByParts(smallparts, nXRayAQTime, true);
  649. }
  650. }
  651. else if (workmode == OTS_X_RAY_SCAN_MODE.FeatureMode)
  652. {
  653. uint nXRayAQTime;
  654. if (bigparts.Count > 0)
  655. {
  656. log.Info("Begin to collect xraydata:" + bigparts.Count + " on " + OTS_X_RAY_SCAN_MODE.FeatureMode.ToString());
  657. nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime();
  658. m_EDSController.GetXRayByFeatures(bigparts, nXRayAQTime, true);
  659. }
  660. if (smallparts.Count > 0)
  661. {
  662. Thread.Sleep(1000);
  663. log.Info("Begin to collect xraydata:" + smallparts.Count + " on " + OTS_X_RAY_SCAN_MODE.PointMode.ToString());
  664. nXRayAQTime = (uint)pXRayParam.GetSmallPartXrayTime();
  665. m_EDSController.GetXRayByParts(smallparts, nXRayAQTime, true);
  666. }
  667. }
  668. else if (workmode == OTS_X_RAY_SCAN_MODE.ExpandMode)
  669. {
  670. uint nXRayAQTime;
  671. if (bigparts.Count > 0)
  672. {
  673. log.Info("Begin to collect xraydata:" + bigparts.Count + " on " + OTS_X_RAY_SCAN_MODE.FeatureMode.ToString());
  674. nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime();
  675. m_EDSController.GetXRayByExpandFeatures(bigparts, nXRayAQTime, true);
  676. }
  677. if (smallparts.Count > 0)
  678. {
  679. Thread.Sleep(500);
  680. log.Info("Begin to collect xraydata:" + smallparts.Count + " on " + OTS_X_RAY_SCAN_MODE.PointMode.ToString());
  681. nXRayAQTime = (uint)pXRayParam.GetSmallPartXrayTime();
  682. m_EDSController.GetXRayByParts(smallparts, nXRayAQTime, true);
  683. }
  684. }
  685. else if (workmode == OTS_X_RAY_SCAN_MODE.SubRegionMode)
  686. {
  687. uint nXRayAQTime;
  688. List<COTSParticleClr> allfldparts = curFldData.GetInitialParticles();
  689. curFldData.CreateXrayList(allfldparts);
  690. if (allfldparts.Count > 0)
  691. {
  692. log.Info("Begin to collect xraydata:" + allfldparts.Count + " on " + OTS_X_RAY_SCAN_MODE.FeatureMode.ToString());
  693. nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime();
  694. //find the biggest subparticle of every particle and scan it.
  695. List<COTSParticleClr> scanparts = new List<COTSParticleClr>();
  696. foreach (var p in allfldparts)
  697. {
  698. if (p.GetSubParticles().Count > 0)
  699. {
  700. var subps = p.GetSubParticles();
  701. var maxP = subps[0];
  702. foreach (var sp in subps)
  703. {
  704. var area = sp.GetActualArea();
  705. if (area > maxP.GetActualArea())
  706. {
  707. maxP = sp;
  708. }
  709. }
  710. scanparts.Add(maxP);
  711. }
  712. else
  713. {
  714. scanparts.Add(p);
  715. }
  716. }
  717. m_EDSController.GetXRayByParts(scanparts, nXRayAQTime, true);
  718. for (int i = 0; i < allfldparts.Count; i++)
  719. {
  720. var xray = scanparts[i].GetXray();
  721. allfldparts[i].SetXray(xray);
  722. }
  723. }
  724. curFldData.SetListAnalysisParticles(allfldparts);
  725. }
  726. }
  727. public virtual void QuantifyParticlesXrayData(COTSField curFldData)
  728. {
  729. var parts = curFldData.GetListXrayParticles();
  730. foreach (var p in parts)
  731. {
  732. m_EDSController.QuantifyXrayByPart(p);
  733. }
  734. }
  735. // Cumulate field data info
  736. public virtual bool CumulateFieldData( List<COTSParticleClr> listParticles, double a_nMeasuredArea)
  737. {
  738. // get measure result items of the sample
  739. CMsrResultItems pMsrResults = m_Sample.GetMsrResults();
  740. // go through the particles list
  741. foreach (COTSParticleClr pParticle in listParticles)
  742. {
  743. // create a measure result item
  744. pMsrResults.CumulateMeasureResult(pParticle);
  745. }
  746. pMsrResults.CumulateMeasuredArea(a_nMeasuredArea);
  747. // cumulate ratio
  748. double dRatio = pMsrResults.GetTotalParticleArea();
  749. dRatio = dRatio / pMsrResults.GetMeasuredArea();
  750. pMsrResults.SetRatio(dRatio);
  751. m_Sample.SetMsrResults(pMsrResults);
  752. return true;
  753. }
  754. public bool SaveFieldData(COTSField fldData, string filedFileFoler)
  755. {
  756. string strFieldFileFolder = filedFileFoler;
  757. CBSEImageFileMgr pBSEImgFileMgr = new CBSEImageFileMgr();
  758. pBSEImgFileMgr.SetBSEImg(fldData.GetBSEImage());
  759. int nId = fldData.GetId();
  760. string sFieldId;
  761. sFieldId = nId.ToString();
  762. string strBSEFilePathname = strFieldFileFolder + "\\" + m_pSampleRstFile.SMPL_MSR_RESULT_FIELDS_BSE + sFieldId + pBSEImgFileMgr.BMP_IMG_FILE_EXT;
  763. if (!pBSEImgFileMgr.SaveIntoBitmap(strBSEFilePathname))
  764. {
  765. log.Error("SaveFieldFiles: save BSE file failed.");
  766. return false;
  767. }
  768. if (fldData.particleImages.Count > 0)
  769. {
  770. for (int i=0;i<fldData.particleImages.Count;i++)
  771. {
  772. strBSEFilePathname= m_pSampleRstFile.GetParticleImageFolder() + "\\" + sFieldId +"_" +i.ToString()+pBSEImgFileMgr.BMP_IMG_FILE_EXT;
  773. pBSEImgFileMgr.SetBSEImg(fldData.particleImages[i]);
  774. pBSEImgFileMgr.SaveIntoBitmap(strBSEFilePathname);
  775. }
  776. }
  777. // IncA Data list
  778. CIncAFileMgr pDBFileMgr = m_pSampleRstFile.DBFileMgr;
  779. pDBFileMgr.SaveStatusDataToDB();
  780. var fldDB = pDBFileMgr.GetFieldDB();
  781. log.Warn("Start saving particle data.");
  782. var fldcmd = fldDB.GetSavingAFieldcmdObj(fldData.GetId(), fldData.GetOTSPosition(), fldData.GetSemPos());
  783. List<KeyValuePair<string, System.Data.SQLite.SQLiteParameter[]>> fldcmds = new List<KeyValuePair<string, System.Data.SQLite.SQLiteParameter[]>>();
  784. fldcmds.Add(fldcmd);
  785. pDBFileMgr.ExecuteNonQueryBatch(ref fldcmds);
  786. //remomove the invalid particles
  787. var cmds = pDBFileMgr.GetSavingParticleDataToDBCmds(fldData.GetListAnalysisParticles(), fldData.GetOTSPosition());
  788. pDBFileMgr.ExecuteNonQueryBatch(ref cmds);
  789. CPosXrayDBMgr PosXrayDBMgr = pDBFileMgr.GetPosXrayDBMgr();
  790. var listAnalysisPosXray = new List<CPosXrayClr>();
  791. foreach (var p in fldData.GetListXrayParticles())
  792. {
  793. listAnalysisPosXray.Add(p.GetXray());
  794. }
  795. var cmds1 = PosXrayDBMgr.GetSavingXrayCmds(listAnalysisPosXray, true);
  796. pDBFileMgr.ExecuteNonQueryBatch(ref cmds1);
  797. return true;
  798. }
  799. protected void SaveFieldMgrData()
  800. {
  801. while (bSaveThreadWorking)
  802. {
  803. while (fieldQueue.Count() > 0)
  804. {
  805. COTSField f = fieldQueue.Dequeue();
  806. //save to disk first ,then pop . if the size is 0,then we know all the saving work is done.
  807. log.Info("Begin to save particles data! particle num:" + f.GetListAnalysisParticles().Count);
  808. SaveFieldData(f, m_pSampleRstFile.GetFieldFileSubFolderStr());
  809. }
  810. if (fieldQueue.Count() == 0)
  811. {
  812. bSaveThreadWorking = false; //must set this flag,so the main thread can know this thread has exited.
  813. log.Warn("finished batch saving");
  814. return;
  815. }
  816. }
  817. return;
  818. }
  819. private void SendFieldParticlesInfoToGUI(COTSField curFld,CMsrSampleStatus pStatus)
  820. {
  821. double measuredArea = 0; // this area should be the field area
  822. var a_pBSEImg = curFld.GetBSEImage();
  823. double dPixelSize = curFld.GetPixelSize();
  824. measuredArea = a_pBSEImg.GetHeight() * a_pBSEImg.GetWidth() * dPixelSize * dPixelSize; //Get measured area
  825. CumulateFieldData(curFld.GetListAnalysisParticles(), measuredArea);
  826. log.Info("Send field data to screen!");
  827. ST_MSTMsg MsgFieldEnd = new ST_MSTMsg(m_Sample,curFld);
  828. MsgFieldEnd.InitFieldDataMsg();
  829. m_pMsrThread.SendMessageToMeasureGUI(MsgFieldEnd);
  830. }
  831. protected void StartSaveFileThread(ref COTSField a_pFieldMgr)
  832. {
  833. fieldQueue.Enqueue(a_pFieldMgr);
  834. if (fieldQueue.Count() > 0) //if there's data in the queue and the previous thread has finished then start a new thread.
  835. {
  836. if (bSaveThreadWorking == false)
  837. {
  838. bSaveThreadWorking = true;
  839. m_thread_ptr = new System.Threading.Thread(this.SaveFieldMgrData);//m_thread_ptr = shared_ptr<thread>(new thread(&CSmplMeasureInc::SaveFieldMgrData, this));
  840. m_thread_ptr.IsBackground = true;
  841. m_thread_ptr.Start();
  842. }
  843. }
  844. }
  845. }
  846. }