CSmplMeasure.cs 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  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.GetMsrThreadStatus();
  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. }
  267. }
  268. if (hardWareDelay > 0)
  269. {
  270. Thread.Sleep(hardWareDelay);
  271. }
  272. return true;
  273. }
  274. // Acquire a BSE image
  275. CBSEImgClr AcquireABSEImage()
  276. {
  277. // BSE image
  278. CBSEImgClr pBSEImage = null;
  279. // get scan controller
  280. var pScanController = m_ScanHardwareMgr;
  281. pBSEImage = pScanController.AcquireBSEImage();
  282. return pBSEImage;
  283. }
  284. public bool IsLowCounts(COTSParticleClr particle)
  285. {
  286. COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam();
  287. if (pXRayParam.GetUsingXray() == true)
  288. {
  289. var thecount = particle.GetXray().GetTotalCount();
  290. var expect = pXRayParam.GetAnalyExpCount();
  291. if (thecount < expect)
  292. {
  293. particle.SetType((int)OTS_PARTICLE_TYPE.LOW_COUNT);
  294. particle.SetClassifyId((int)OTS_PARTICLE_TYPE.LOW_COUNT);
  295. particle.SetTypeColor("#000000");
  296. particle.SetTypeName("LowCounts");
  297. return true;
  298. }
  299. }
  300. return false;
  301. }
  302. public virtual void ClassifyFieldParticles(COTSField curFldData)
  303. {
  304. return;
  305. }
  306. private bool GetSEMDataGnrFromHw(ref CSEMDataGnr SemDataGnr)
  307. {
  308. double kv = 0, brightness = 0, contrast = 0;
  309. var hw = SemController.GetSEMController();
  310. hw.GetSemHighTension(ref kv);
  311. hw.GetSemBrightness(ref brightness);
  312. hw.GetSemContrast(ref contrast);
  313. SemDataGnr.SetValue(kv, brightness, contrast);
  314. return true;
  315. }
  316. public void DoMeasureForOneSample()
  317. {
  318. try
  319. {
  320. // let the main thread to know that this sample measurement starts
  321. var pStatus = m_Sample.GetMsrStatus();
  322. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS);
  323. // set current time to current time
  324. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.START);
  325. // let main App know that the sample begin to measure
  326. ST_MSTMsg MsgSmpStart = new ST_MSTMsg(m_Sample);
  327. MsgSmpStart.InitSampleStartMsg();
  328. m_pMsrThread.SendMessageToMeasureGUI(MsgSmpStart);
  329. log.Info(m_Sample.GetName() + " Measurement started!");
  330. // get SEM controller to set magnification and working distance
  331. if (!SetSEMDataMrs(m_Sample.GetSEMDataMsr()))
  332. {
  333. log.Error("DoMeasure: fail to set SEM data.");
  334. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  335. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  336. return;
  337. }
  338. // set the BSE scan param
  339. if (!InitScanControllerBSEParam())
  340. {
  341. log.Error("DoMeasure: fail to set BSE param.");
  342. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  343. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  344. return;
  345. }
  346. var pSEMDataGnr = new CSEMDataGnr();
  347. log.Info("Get current Kv, Brightness and Contrast!");
  348. GetSEMDataGnrFromHw(ref pSEMDataGnr);
  349. m_pSampleRstFile.SetSEMDataGnr(pSEMDataGnr);
  350. // record SEM data
  351. COTSMsrPrjResultData pProjMgrFile = m_pMsrThread.GetProjResultData();
  352. CSEMStageData pSEMStageData = pProjMgrFile.GetSEMStageData();
  353. m_pSampleRstFile.SetSEMStageData(pSEMStageData);
  354. CSampleHolder pSampleStage = pProjMgrFile.GetStageHolder();
  355. m_pSampleRstFile.SetSEMStage(pSampleStage);
  356. //-----save the static measure result file data into xml file and the dynamic data of every field will be saved into sqlite database
  357. log.Info("Create result file!");
  358. if (!m_pSampleRstFile.CreateResultFiles())
  359. {// failed to call measure result file Save method
  360. log.Error("DoMeasure: failed to call measure result file Save method.");
  361. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  362. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  363. return;
  364. }
  365. //------
  366. var FldDatas = m_Sample.GetFieldsData();
  367. for (int i = 0; i < FldDatas.Count; ++i)
  368. {// check and break if stop button is clicked
  369. try
  370. {
  371. var curFld = FldDatas[i];
  372. if (curFld.GetIsMeasureComplete())
  373. {
  374. continue;
  375. }
  376. if (curFld.Enable == false)
  377. {
  378. continue;
  379. }
  380. if (IsPaused())
  381. {// measure stopped
  382. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.PAUSED);
  383. // record end time
  384. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  385. //must wait for the saving data thread finished,or we'll get null pointer exception when we stop the measure process.
  386. while (fieldQueue.Count() > 0)
  387. {
  388. Thread.Sleep(100);
  389. }
  390. SetSEMExteralOff();
  391. // update thread measure status class, let the main thread know that this sample measurement stopped
  392. ST_MSTMsg MsgSmpStop = new ST_MSTMsg(m_Sample);
  393. MsgSmpStop.InitSamplePausedMsg();
  394. m_pMsrThread.SendMessageToMeasureGUI(MsgSmpStop);
  395. while (IsPaused())
  396. {
  397. Thread.Sleep(300);
  398. }
  399. }
  400. if (IsAborted())
  401. {// measure stopped
  402. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.STOPPED);
  403. // record end time
  404. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  405. //must wait for the saving data thread finished,or we'll get null pointer exception when we stop the measure process.
  406. while (fieldQueue.Count() > 0)
  407. {
  408. Thread.Sleep(100);
  409. }
  410. break;
  411. }
  412. // check if sample measurement completes
  413. COTSImgScanPrm pScanParam = m_Sample.GetMsrParams().GetImageScanParam();
  414. if (IsSampleOver(pScanParam))
  415. {
  416. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
  417. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.COMPLT);
  418. break;
  419. }
  420. var BCregulater = m_pMsrThread.BCregulater;
  421. if (BCregulater.checkPeriodTime())
  422. {
  423. BCregulater.DoBrightnessContrastAdjust();
  424. }
  425. // get a field center
  426. System.Drawing.PointF poiFieldCentre = curFld.GetOTSPosition();
  427. // update thread measure status class, let the main thread know that starts a new field
  428. ST_MSTMsg MsgFieldStart = new ST_MSTMsg(m_Sample, curFld);
  429. MsgFieldStart.InitFieldStartMsg();
  430. m_pMsrThread.SendMessageToMeasureGUI(MsgFieldStart);
  431. int fldNo = curFld.GetId();
  432. log.Warn("Current field:" + fldNo.ToString());
  433. // move SEM to the field center
  434. if (!MoveSEMToPoint(poiFieldCentre))
  435. {// failed to move SEM to the position
  436. log.Error("DoMeasure: failed to move SEM to the field centre point.");
  437. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  438. // record end time
  439. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  440. return;
  441. }
  442. log.Info("Begin to Acquire BSE image!");
  443. // take BSE image for the fields
  444. CBSEImgClr pBSEImg = AcquireABSEImage();
  445. // let the main thread to know that image process is completed
  446. if (pBSEImg == null)
  447. {
  448. log.Error("ImageProcess: can't get BSE image.");
  449. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  450. return;
  451. }
  452. curFld.SetBSEImage(pBSEImg);
  453. //BSEData
  454. ST_MSTMsg MsgFieldBSE = new ST_MSTMsg(m_Sample, curFld);
  455. MsgFieldBSE.InitFieldBSEImageMsg();
  456. m_pMsrThread.SendMessageToMeasureGUI(MsgFieldBSE);
  457. log.Info("Acquire BSE image success! Processing image...");
  458. // image process
  459. FieldImageProcess(curFld);
  460. MsgFieldBSE.InitFieldBSEAnalysisPartsDataMsg();
  461. m_pMsrThread.SendMessageToMeasureGUI(MsgFieldBSE);
  462. if (m_ifAquireClearParticleImage)
  463. {
  464. var listAnalysisParts = curFld.GetListAnalysisParticles();
  465. foreach (var p in listAnalysisParts)
  466. {
  467. Rectangle r = (Rectangle)p.GetParticleRect();
  468. var img = m_ScanHardwareMgr.AcquireRectangleBSEImage(r);
  469. if (img != null)
  470. {
  471. curFld.particleImages.Add(img);
  472. }
  473. }
  474. }
  475. COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam();
  476. if (pXRayParam.GetUsingXray() == true)
  477. {
  478. foreach (var p in curFld.GetListAnalysisParticles())
  479. {
  480. p.SetIsXrayParticle(true);
  481. }
  482. try
  483. {
  484. CollectParticlesXrayData(curFld);
  485. }
  486. catch (Exception e)
  487. {
  488. log.Error(e.Message);
  489. }
  490. }
  491. m_Sample.GetMsrStatus().SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
  492. curFld.SetIsMeasureComplete(true);
  493. log.Info("Begin to classify particles! particle num:" + curFld.GetListAnalysisParticles().Count);
  494. try
  495. {
  496. ClassifyFieldParticles(curFld);
  497. }
  498. catch (Exception e)
  499. {
  500. log.Error(e.Message);
  501. }
  502. MsgFieldBSE.InitFieldSTDColoredPartsDataMsg();
  503. m_pMsrThread.SendMessageToMeasureGUI(MsgFieldBSE);
  504. //start db save
  505. StartSaveFileThread(ref curFld);
  506. // record
  507. pStatus.AddCompletedFieldCenter(curFld.GetOTSPosition());
  508. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  509. SendFieldParticlesInfoToGUI(curFld, m_Sample.GetMsrStatus());
  510. }
  511. catch (Exception e)
  512. {
  513. log.Error(e.Message);
  514. }
  515. }
  516. while (bSaveThreadWorking)//wait untill all the field data has been saved.
  517. {
  518. Thread.Sleep(1000);
  519. log.Warn("db saving!");
  520. }
  521. TheLastWorkOfSampleMeasure();
  522. }
  523. catch (Exception e)
  524. {
  525. log.Error(e.Message);
  526. }
  527. finally
  528. {
  529. SetSEMExteralOff();
  530. }
  531. }
  532. public void TheLastWorkOfSampleMeasure()
  533. {
  534. COTSSample theSample = m_Sample;
  535. var pStatus = theSample.GetMsrStatus();
  536. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.COMPLT);
  537. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
  538. // let main thread to know that this sample measurement completes
  539. ST_MSTMsg MsgSmplEnd = new ST_MSTMsg(m_Sample);
  540. MsgSmplEnd.InitSampleCompleteMsg();
  541. m_pMsrThread.SendMessageToMeasureGUI(MsgSmplEnd);
  542. }
  543. public bool DoMEasureForReMeasure()
  544. {
  545. return true;
  546. }
  547. public virtual void FieldImageProcess(COTSField curFldData)
  548. {
  549. PointF fldCenter = curFldData.GetOTSPosition();
  550. CSEMStageData a_pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData();
  551. PointF semPos = new Point();
  552. a_pCSEMStageData.ConvertOTSToSEMCoord(fldCenter, ref semPos);
  553. curFldData.SetSemPos(semPos);
  554. //first step:remove background of the bse image and compound all the finded particles.
  555. CSampleParam pMsrParam = m_Sample.GetMsrParams();
  556. COTSImageProcParam pImgProcessParam = pMsrParam.GetImageProcessParam();
  557. log.Info("Begin to process image and get all particles!");
  558. //according to the ECD scope,filter out the effective particles,remove the noise.
  559. curFldData.GetOriginalParticles(m_Sample.GetMsrParams(), m_Sample.CalculatePixelSize());
  560. if (curFldData.Sample.GetMsrParams().GetImageProcessParam().GetBGRemoveType() == OTS_BGREMOVE_TYPE.MATRIX)
  561. {
  562. curFldData.SetListAnalysisParticles(curFldData.GetAllParticles());
  563. }
  564. else
  565. {
  566. log.Info("Begin to filter particles!");
  567. curFldData.FilterParticles(m_Sample.GetMsrParams().GetXRayParam());//filter according to the xraylimit and outermost border
  568. log.Info("Begin to Calculate the image property of every particle!");
  569. var analysisparts = curFldData.GetListAnalysisParticles();
  570. curFldData.CalParticleImageProp(analysisparts);//calculate particle image property such as feret diameter, DMAX etc.
  571. curFldData.SelectParticlesAccordingImgProp(pImgProcessParam);
  572. var overlap = pImgProcessParam.GetOverlapParam();
  573. if (overlap > 0)
  574. {
  575. try
  576. {
  577. curFldData.RemoveDuplicateOverlapParticles(overlap);
  578. }
  579. catch (Exception e)
  580. {
  581. log.Error(e.Message);
  582. }
  583. }
  584. }
  585. curFldData.CalculateParticleAbsolutPos(m_pMsrThread.GetProjResultData().GetSEMStageData());
  586. curFldData.InitParticles(pImgProcessParam);
  587. return ;
  588. }
  589. public virtual void CollectParticlesXrayData(COTSField curFldData)
  590. {
  591. var allParts = curFldData.GetListXrayParticles();
  592. var smallparts = new List<COTSParticleClr>();
  593. var bigparts = new List<COTSParticleClr>();
  594. double quantifyThreshold = m_Sample.GetMsrParams().GetXRayParam().GetFeatureModeMinSize();
  595. foreach (var part in allParts)
  596. {
  597. double equalCircleDiameter = Math.Sqrt(part.GetActualArea() / 3.14159) * 2f;
  598. if (equalCircleDiameter < quantifyThreshold)
  599. {
  600. smallparts.Add(part);
  601. }
  602. else
  603. {
  604. bigparts.Add(part);
  605. }
  606. }
  607. log.Info("SmallQuantifyParts (<" + quantifyThreshold.ToString("f2") + "): " + smallparts.Count);
  608. log.Info("BigQuantifyParts (>=" + quantifyThreshold.ToString("f2") + "): " + bigparts.Count);
  609. curFldData.CreateXrayList(smallparts);
  610. curFldData.CreateXrayList(bigparts);
  611. // get x-ray parameters
  612. COTSXRayParam pXRayParam = m_Sample.GetMsrParams().GetXRayParam();
  613. var workmode = pXRayParam.GetScanMode();
  614. if (workmode == OTS_X_RAY_SCAN_MODE.PointMode)
  615. {
  616. uint nXRayAQTime;
  617. if (bigparts.Count > 0)
  618. {
  619. nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime();
  620. log.Info("Begin to collect xraydata:" + bigparts.Count +"(" +nXRayAQTime.ToString()+") on " + workmode.ToString());
  621. m_EDSController.GetXRayByParts(bigparts, nXRayAQTime, true);
  622. }
  623. if (smallparts.Count > 0)
  624. {
  625. Thread.Sleep(1000);//add delay here,or else the eds system will halt.
  626. nXRayAQTime = (uint)pXRayParam.GetSmallPartXrayTime();
  627. log.Info("Begin to collect xraydata:" + smallparts.Count + "(" + nXRayAQTime.ToString() + ") on " + workmode.ToString());
  628. m_EDSController.GetXRayByParts(smallparts, nXRayAQTime, true);
  629. }
  630. }
  631. else if (workmode == OTS_X_RAY_SCAN_MODE.FeatureMode)
  632. {
  633. uint nXRayAQTime;
  634. if (bigparts.Count > 0)
  635. {
  636. log.Info("Begin to collect xraydata:" + bigparts.Count + " on " + OTS_X_RAY_SCAN_MODE.FeatureMode.ToString());
  637. nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime();
  638. m_EDSController.GetXRayByFeatures(bigparts, nXRayAQTime, true);
  639. }
  640. if (smallparts.Count > 0)
  641. {
  642. Thread.Sleep(1000);
  643. log.Info("Begin to collect xraydata:" + smallparts.Count + " on " + OTS_X_RAY_SCAN_MODE.PointMode.ToString());
  644. nXRayAQTime = (uint)pXRayParam.GetSmallPartXrayTime();
  645. m_EDSController.GetXRayByParts(smallparts, nXRayAQTime, true);
  646. }
  647. }
  648. else if (workmode == OTS_X_RAY_SCAN_MODE.ExpandMode)
  649. {
  650. uint nXRayAQTime;
  651. if (bigparts.Count > 0)
  652. {
  653. log.Info("Begin to collect xraydata:" + bigparts.Count + " on " + OTS_X_RAY_SCAN_MODE.FeatureMode.ToString());
  654. nXRayAQTime = (uint)pXRayParam.GetMidAnalyAQTime();
  655. m_EDSController.GetXRayByExpandFeatures(bigparts, nXRayAQTime, true);
  656. }
  657. if (smallparts.Count > 0)
  658. {
  659. Thread.Sleep(500);
  660. log.Info("Begin to collect xraydata:" + smallparts.Count + " on " + OTS_X_RAY_SCAN_MODE.PointMode.ToString());
  661. nXRayAQTime = (uint)pXRayParam.GetSmallPartXrayTime();
  662. m_EDSController.GetXRayByParts(smallparts, nXRayAQTime, true);
  663. }
  664. }
  665. return;
  666. }
  667. public virtual void QuantifyParticlesXrayData(COTSField curFldData)
  668. {
  669. var parts = curFldData.GetListXrayParticles();
  670. foreach (var p in parts)
  671. {
  672. m_EDSController.QuantifyXrayByPart(p);
  673. }
  674. }
  675. // Cumulate field data info
  676. public virtual bool CumulateFieldData( List<COTSParticleClr> listParticles, double a_nMeasuredArea)
  677. {
  678. // get measure result items of the sample
  679. CMsrResultItems pMsrResults = m_Sample.GetMsrResults();
  680. // go through the particles list
  681. foreach (COTSParticleClr pParticle in listParticles)
  682. {
  683. // create a measure result item
  684. pMsrResults.CumulateMeasureResult(pParticle);
  685. }
  686. pMsrResults.CumulateMeasuredArea(a_nMeasuredArea);
  687. // cumulate ratio
  688. double dRatio = pMsrResults.GetTotalParticleArea();
  689. dRatio = dRatio / pMsrResults.GetMeasuredArea();
  690. pMsrResults.SetRatio(dRatio);
  691. m_Sample.SetMsrResults(pMsrResults);
  692. return true;
  693. }
  694. public bool SaveFieldData(COTSField fldData, string filedFileFoler)
  695. {
  696. string strFieldFileFolder = filedFileFoler;
  697. CBSEImageFileMgr pBSEImgFileMgr = new CBSEImageFileMgr();
  698. pBSEImgFileMgr.SetBSEImg(fldData.GetBSEImage());
  699. int nId = fldData.GetId();
  700. string sFieldId;
  701. sFieldId = nId.ToString();
  702. string strBSEFilePathname = strFieldFileFolder + "\\" + m_pSampleRstFile.SMPL_MSR_RESULT_FIELDS_BSE + sFieldId + pBSEImgFileMgr.BMP_IMG_FILE_EXT;
  703. if (!pBSEImgFileMgr.SaveIntoBitmap(strBSEFilePathname))
  704. {
  705. log.Error("SaveFieldFiles: save BSE file failed.");
  706. return false;
  707. }
  708. if (fldData.particleImages.Count > 0)
  709. {
  710. for (int i=0;i<fldData.particleImages.Count;i++)
  711. {
  712. strBSEFilePathname= m_pSampleRstFile.GetParticleImageFolder() + "\\" + sFieldId +"_" +i.ToString()+pBSEImgFileMgr.BMP_IMG_FILE_EXT;
  713. pBSEImgFileMgr.SetBSEImg(fldData.particleImages[i]);
  714. pBSEImgFileMgr.SaveIntoBitmap(strBSEFilePathname);
  715. }
  716. }
  717. // IncA Data list
  718. CIncAFileMgr pDBFileMgr = m_pSampleRstFile.DBFileMgr;
  719. pDBFileMgr.SaveStatusDataToDB();
  720. var fldDB = pDBFileMgr.GetFieldDB();
  721. log.Warn("Start saving particle data.");
  722. var fldcmd = fldDB.GetSavingAFieldcmdObj(fldData.GetId(), fldData.GetOTSPosition(), fldData.GetSemPos());
  723. List<KeyValuePair<string, System.Data.SQLite.SQLiteParameter[]>> fldcmds = new List<KeyValuePair<string, System.Data.SQLite.SQLiteParameter[]>>();
  724. fldcmds.Add(fldcmd);
  725. pDBFileMgr.ExecuteNonQueryBatch(ref fldcmds);
  726. //remomove the invalid particles
  727. var cmds = pDBFileMgr.GetSavingParticleDataToDBCmds(fldData.GetListAnalysisParticles(), fldData.GetOTSPosition());
  728. pDBFileMgr.ExecuteNonQueryBatch(ref cmds);
  729. CPosXrayDBMgr PosXrayDBMgr = pDBFileMgr.GetPosXrayDBMgr();
  730. var listAnalysisPosXray = new List<CPosXrayClr>();
  731. foreach (var p in fldData.GetListXrayParticles())
  732. {
  733. listAnalysisPosXray.Add(p.GetXray());
  734. }
  735. var cmds1 = PosXrayDBMgr.GetSavingXrayCmds(listAnalysisPosXray, true);
  736. pDBFileMgr.ExecuteNonQueryBatch(ref cmds1);
  737. return true;
  738. }
  739. protected void SaveFieldMgrData()
  740. {
  741. while (bSaveThreadWorking)
  742. {
  743. while (fieldQueue.Count() > 0)
  744. {
  745. COTSField f = fieldQueue.Dequeue();
  746. //save to disk first ,then pop . if the size is 0,then we know all the saving work is done.
  747. log.Info("Begin to save particles data! particle num:" + f.GetListAnalysisParticles().Count);
  748. SaveFieldData(f, m_pSampleRstFile.GetFieldFileSubFolderStr());
  749. }
  750. if (fieldQueue.Count() == 0)
  751. {
  752. bSaveThreadWorking = false; //must set this flag,so the main thread can know this thread has exited.
  753. log.Warn("finished batch saving");
  754. return;
  755. }
  756. }
  757. return;
  758. }
  759. private void SendFieldParticlesInfoToGUI(COTSField curFld,CMsrSampleStatus pStatus)
  760. {
  761. double measuredArea = 0; // this area should be the field area
  762. var a_pBSEImg = curFld.GetBSEImage();
  763. double dPixelSize = curFld.GetPixelSize();
  764. measuredArea = a_pBSEImg.GetHeight() * a_pBSEImg.GetWidth() * dPixelSize * dPixelSize; //Get measured area
  765. CumulateFieldData(curFld.GetListAnalysisParticles(), measuredArea);
  766. log.Info("Send field data to screen!");
  767. ST_MSTMsg MsgFieldEnd = new ST_MSTMsg(m_Sample,curFld);
  768. MsgFieldEnd.InitFieldDataMsg();
  769. m_pMsrThread.SendMessageToMeasureGUI(MsgFieldEnd);
  770. }
  771. protected void StartSaveFileThread(ref COTSField a_pFieldMgr)
  772. {
  773. fieldQueue.Enqueue(a_pFieldMgr);
  774. if (fieldQueue.Count() > 0) //if there's data in the queue and the previous thread has finished then start a new thread.
  775. {
  776. if (bSaveThreadWorking == false)
  777. {
  778. bSaveThreadWorking = true;
  779. m_thread_ptr = new System.Threading.Thread(this.SaveFieldMgrData);//m_thread_ptr = shared_ptr<thread>(new thread(&CSmplMeasureInc::SaveFieldMgrData, this));
  780. m_thread_ptr.IsBackground = true;
  781. m_thread_ptr.Start();
  782. }
  783. }
  784. }
  785. }
  786. }