CSmplMeasure.cs 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using OTSModelSharp.ServiceInterface;
  7. using static OTSDataType.otsdataconst;
  8. using OTSDataType;
  9. using System.Diagnostics;
  10. using System.Drawing;
  11. using System.Threading;
  12. using OTSModelSharp.DTLBase;
  13. using OTSCLRINTERFACE;
  14. namespace OTSModelSharp
  15. {
  16. using CHoleBSEImgsList = List<CHoleBSEImg>;
  17. class CSmplMeasure
  18. {
  19. protected static NLog.Logger log ;
  20. protected bool bSaveThreadWorking;
  21. protected System.Threading.Thread m_thread_ptr;
  22. protected COTSSample m_Sample;
  23. protected CMeasure m_pMsrThread;
  24. string m_strWorkingFolder;
  25. protected CSmplMsrResult m_pSampleRstFile;
  26. CHoleBSEImgsList m_listHoleBSEImg;
  27. //CFunExportClass loger;
  28. protected SemController m_SemHardwareMgr;
  29. protected ScanController m_ScanHardwareMgr;
  30. protected EDSController m_EDSHardwareMgr;
  31. protected Queue<COTSFieldData> fieldQueue=new Queue<COTSFieldData>();
  32. protected COTSFieldData curFldData;
  33. protected IClassifyEngine m_classifyEngine;
  34. public CSmplMeasure()
  35. {
  36. log = NLog.LogManager.GetCurrentClassLogger();
  37. m_pSampleRstFile = new CSmplMsrResult();
  38. m_SemHardwareMgr = new SemController();
  39. m_ScanHardwareMgr = new ScanController();
  40. m_EDSHardwareMgr = new EDSController();
  41. m_listHoleBSEImg = new CHoleBSEImgsList();
  42. }
  43. public CSmplMeasure( string a_strWorkingFolder, COTSSample a_pSample)
  44. {
  45. log = NLog.LogManager.GetCurrentClassLogger();
  46. m_strWorkingFolder = a_strWorkingFolder;
  47. m_pSampleRstFile = new CSmplMsrResult( a_strWorkingFolder, a_pSample);// new CSmplMsrResultFile(m_strWorkingFolder,a_pSample);
  48. m_SemHardwareMgr = new SemController();
  49. m_ScanHardwareMgr = new ScanController();
  50. m_EDSHardwareMgr = new EDSController();
  51. m_listHoleBSEImg = new CHoleBSEImgsList();
  52. m_Sample = a_pSample;
  53. }
  54. public void SetSample(COTSSample a_pSample)
  55. {
  56. m_Sample = a_pSample;
  57. m_pSampleRstFile.SetSample(a_pSample);
  58. }
  59. public void SetMsrThread(CMeasure mt)
  60. {
  61. m_pMsrThread = mt;
  62. }
  63. bool SetSEMDataMrs()
  64. {
  65. var pSEMDataMsr = m_Sample.GetSEMDataMsr();
  66. //ASSERT(pSEMDataMsr);
  67. double dMag = pSEMDataMsr.GetMagnification();
  68. double dWorkDis = pSEMDataMsr.GetWorkingDistance();
  69. //CSemBasePtr pSEMCtrlPtr = GetSEMControl();
  70. var pSEMCtrl = m_pMsrThread.GetSEMController();
  71. // get SEM controller
  72. if (!pSEMCtrl.IsConnected())
  73. {
  74. if (!pSEMCtrl.Connect())
  75. {
  76. log.Error("SetSEMDataMrs: can't connect SEM.");
  77. return false;
  78. }
  79. }
  80. log.Info("set magnification:" + dMag.ToString());
  81. log.Info("set Working Distance:" + dWorkDis.ToString());
  82. pSEMCtrl.SetMagnification(dMag);
  83. pSEMCtrl.SetWorkingDistance(dWorkDis);
  84. return true;
  85. }
  86. bool SetSEMExteralOn()
  87. {
  88. var pSEMCtrl = m_SemHardwareMgr;
  89. // get SEM controller
  90. if (!pSEMCtrl.IsConnected())
  91. {
  92. if (!pSEMCtrl.Connect())
  93. {
  94. log.Error("SetSEMExteralOn: can't connect SEM.");
  95. return false;
  96. }
  97. }
  98. log.Warn("Set Scan Exteral on!");
  99. pSEMCtrl.SetScanExternal(true);
  100. return true;
  101. }
  102. // set SEM external off
  103. bool SetSEMExteralOff()
  104. {
  105. var pSEMCtrlPtr = m_SemHardwareMgr;
  106. // get SEM controller
  107. if (!pSEMCtrlPtr.IsConnected())
  108. {
  109. if (!pSEMCtrlPtr.Connect())
  110. {
  111. log.Error("SetSEMExteralOff: can't connect SEM.");
  112. return false;
  113. }
  114. }
  115. log.Warn("Set SEM Exteral Off!");
  116. pSEMCtrlPtr.SetScanExternal(false);
  117. return true;
  118. }
  119. bool SetBSEParam()
  120. {
  121. // get SEM controller
  122. var pSEMController = m_SemHardwareMgr;
  123. // get scan controller
  124. var pScanController = m_ScanHardwareMgr;
  125. // scan parameters
  126. var pMsrParam = m_Sample.GetMsrParams();
  127. var pImgScanParam = pMsrParam.GetImageScanParam();
  128. // get image size
  129. var nImageSizeId = pImgScanParam.GetImageResulotion();
  130. int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId;
  131. Size sizePixelImage = RESOLUTION_VALUE[nResulotionId];
  132. // get SEM controller
  133. if (!pSEMController.IsConnected())
  134. {
  135. if (!pSEMController.Connect())
  136. {
  137. log.Error("SetBSEParam: can't connect SEM.");
  138. return false;
  139. }
  140. }
  141. // get dwell time
  142. OTS_IMAGE_SCANSPEED_OPTIONS nDwellTime = pImgScanParam.GetScanImageSpeed();
  143. // convert dwell time to bruker dwell time (8, 16, 32)
  144. int nBrukerDwellTimeId=3;
  145. switch (nDwellTime)
  146. {
  147. case OTS_IMAGE_SCANSPEED_OPTIONS.low:
  148. nBrukerDwellTimeId = 3;
  149. break;
  150. case OTS_IMAGE_SCANSPEED_OPTIONS.meddium:
  151. nBrukerDwellTimeId = 4;
  152. break;
  153. case OTS_IMAGE_SCANSPEED_OPTIONS.high:
  154. nBrukerDwellTimeId = 5;
  155. break;
  156. default:
  157. nBrukerDwellTimeId = 3;
  158. break;
  159. }
  160. long nBrukerDwellTime = OTSDataType.otsdataconst.DWELLTIME_BRUKER_VALUES[nBrukerDwellTimeId];
  161. if (!pScanController.Init())
  162. {
  163. log.Error("SetBSEParam: failed to get scan control.");
  164. return false;
  165. }
  166. // set dwell time
  167. if (!pScanController.SetDwellTime(nBrukerDwellTime))
  168. {
  169. log.Error("SetBSEParam: failed to set dwell time (%d) for bruker system.", nBrukerDwellTime);
  170. return false;
  171. }
  172. // set image size
  173. if (!pScanController.SetImageSize(sizePixelImage.Width,sizePixelImage.Height))
  174. {
  175. // failed to set dwell time
  176. log.Error("SetBSEParam: failed to set dwell time (%d).", sizePixelImage.Height);
  177. return false;
  178. }
  179. return true;
  180. }
  181. bool SetHoleBSEParam()
  182. {
  183. // get SEM controller
  184. var pSEMController = m_SemHardwareMgr;
  185. // get scan controller
  186. var pScanController = m_ScanHardwareMgr;
  187. // scan parameters
  188. var pMsrParam = m_Sample.GetMsrParams();
  189. var pImgScanParam = pMsrParam.GetImageScanParam();
  190. // get image size
  191. var nImageSizeId = pImgScanParam.GetImageResulotion();
  192. int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId;
  193. Size sizePixelImage = RESOLUTION_VALUE[nResulotionId];
  194. // get SEM controller
  195. if (!pSEMController.IsConnected())
  196. {
  197. if (!pSEMController.Connect())
  198. {
  199. log.Error("SetBSEParam: can't connect SEM.");
  200. return false;
  201. }
  202. }
  203. // get dwell time
  204. OTS_IMAGE_SCANSPEED_OPTIONS nDwellTime = pImgScanParam.GetScanImageSpeed();
  205. // convert dwell time to bruker dwell time (6, 16, 32)
  206. long nBrukerDwellTime = DWELLTIME_BRUKER_VALUES[2];// choose the third option, so the dwell time will be 4 . there's no need to change here. it shoud be a const.
  207. if (!pScanController.Init())
  208. {
  209. log.Error("SetBSEParam: failed to get scan control.");
  210. return false;
  211. }
  212. // set dwell time
  213. if (!pScanController.SetDwellTime(nBrukerDwellTime))
  214. {
  215. log.Error("SetBSEParam: failed to set dwell time (%d) for bruker system.", nBrukerDwellTime);
  216. return false;
  217. }
  218. // set image size
  219. if (!pScanController.SetImageSize(sizePixelImage.Width/2, sizePixelImage.Height/2))
  220. {
  221. // failed to set dwell time
  222. log.Error("SetBSEParam: failed to set dwell time (%d).", sizePixelImage.Height);
  223. return false;
  224. }
  225. return true;
  226. }
  227. public void SetWorkingFolder(String a_strWorkingFolder)
  228. {
  229. // add "\\" at the string end if it is not "\\"
  230. if (a_strWorkingFolder.PadRight(1)!="\\")
  231. {
  232. a_strWorkingFolder += "\\";
  233. }
  234. m_strWorkingFolder = a_strWorkingFolder + m_Sample.GetName() + "\\";
  235. }
  236. bool CalculateUnMeasuredFieldsCenters(out List<System.Drawing.Point> a_allpieldcenter,out List<System.Drawing.Point> a_listFieldCenter)
  237. {
  238. // sample measure parameters
  239. CSampleParam pMsrParam = m_Sample.GetMsrParams();
  240. COTSImgScanPrm poImageScanParam = pMsrParam.GetImageScanParam();
  241. CSEMDataMsr poSEMDataMsr = m_Sample.GetSEMDataMsr();
  242. CMsrSampleStatus pStatus = m_Sample.GetMsrStatus();
  243. // measured field centers list
  244. List<System.Drawing.Point> listCompletedCenter = pStatus.GetCompletedFieldsCenter();
  245. // field centers list manager
  246. CFieldPositionMgr pFieldMgr = new CFieldPositionMgr();
  247. // init field centers list manager
  248. if (!pFieldMgr.Init(m_Sample.GetMsrArea(), poImageScanParam, poSEMDataMsr, listCompletedCenter))
  249. {
  250. log.Error("CalculateFieldsCenters: failed to init field centres list manager.");
  251. a_listFieldCenter = new List<System.Drawing.Point>();
  252. a_allpieldcenter = new List<Point>();
  253. return false;
  254. }
  255. // get field centers list
  256. a_listFieldCenter = pFieldMgr.GetUnmeasuredFieldCentrePoints();// GetFieldCentrePoints();
  257. a_allpieldcenter = pFieldMgr.GetFieldCentrePoints();
  258. // ok, return TRUE
  259. return true;
  260. }
  261. protected bool IsAborted()
  262. {
  263. //Debug.Assert(m_pMsrThread == null);
  264. return m_pMsrThread.IsMeasureStopped();
  265. }
  266. bool IsSampleOver(COTSImgScanPrm a_pScanParam, int a_nTotalFields)
  267. {
  268. int nStopMode = (int)a_pScanParam.GetStopMode();
  269. int nStopField = a_pScanParam.GetStopParamFields();
  270. // completed fields number
  271. CMsrSampleStatus pMsrSampleStatus = m_Sample.GetMsrStatus();
  272. int nCompeltedField = pMsrSampleStatus.GetCompletedFields();
  273. CMsrDisplayResults pMsrResults = m_Sample.GetMsrResults();
  274. List<CMsrResultItem> listMsrResult = pMsrResults.GetResultItems();
  275. int nNumParticle = 0;
  276. foreach (var pResult in listMsrResult)
  277. {
  278. if (pResult.GetTypeId() > (int)OTS_PARTCLE_TYPE.NO_ANALYSIS_X_RAY)//summarize the number of the identified particle in this condition
  279. {
  280. nNumParticle += (int)pResult.GetNumber();
  281. }
  282. }
  283. TimeSpan timeSpan = pMsrSampleStatus.GetUsedTime();
  284. int nDay = timeSpan.Days;
  285. int nHour = timeSpan.Hours;
  286. int nMin = timeSpan.Minutes;
  287. int nSec = timeSpan.Seconds;
  288. int nUsedTime = nSec + nMin * 60 + nHour * 3600 + nDay * 86400;
  289. int nParticlAim = a_pScanParam.GetStopParamParticles();
  290. int nMeasTimeAim = a_pScanParam.GetStopParamMeasTime();
  291. bool bRet = true;
  292. switch (nStopMode)
  293. {
  294. case (int)OTS_MEASURE_STOP_MODE.CoverMode:
  295. // completed fields number
  296. if (nCompeltedField < a_nTotalFields)
  297. {
  298. bRet = false;
  299. }
  300. break;
  301. case (int)OTS_MEASURE_STOP_MODE.FieldMode:
  302. if (nCompeltedField < nStopField)
  303. {
  304. bRet = false;
  305. }
  306. break;
  307. case (int)OTS_MEASURE_STOP_MODE.ParticleMode:
  308. if (nNumParticle < nParticlAim)
  309. {
  310. bRet = false;
  311. }
  312. break;
  313. case (int)OTS_MEASURE_STOP_MODE.TimeMode:
  314. if (nUsedTime < nMeasTimeAim)
  315. {
  316. bRet = false;
  317. }
  318. break;
  319. default:
  320. break;
  321. }
  322. return bRet;
  323. }
  324. // move SEM to the point
  325. bool MoveSEMToPoint(System.Drawing.Point a_poi)
  326. {
  327. //add
  328. // get SEM controller
  329. var pSEMController = m_SemHardwareMgr;
  330. Point a_SEMpt = new Point();
  331. CSEMStageData a_pCSEMStageData = m_pMsrThread.GetProjResultData().GetSEMStageData();
  332. if (!a_pCSEMStageData.ConverOTSToSEMPoint(a_poi, ref a_SEMpt))
  333. {
  334. return false;
  335. }
  336. if (!pSEMController.IsConnected())
  337. {
  338. if (!pSEMController.Connect())
  339. {
  340. log.Error("MoveSEMToPoint: can't connect SEM.");
  341. return false;
  342. }
  343. }
  344. log.Info("Begin to move SEM stage to " + a_SEMpt.X + "," + a_SEMpt.Y);
  345. Thread.Sleep(100);
  346. // move SEM to the position (rotation 0)
  347. if (!pSEMController.MoveSEMToPoint(a_SEMpt, 0))
  348. {
  349. log.Error("MoveSEMToPoint: failed to call MoveSEMToPoint method.");
  350. return false;
  351. }
  352. //add
  353. return true;
  354. }
  355. // Acquire a BSE image
  356. CBSEImgClr AcquireABSEImage()
  357. {
  358. // BSE image
  359. CBSEImgClr pBSEImage = null;
  360. // get scan controller
  361. var pScanController = m_ScanHardwareMgr;
  362. pBSEImage = pScanController.AcquireBSEImage(0, 0, 2);
  363. return pBSEImage;
  364. }
  365. public virtual bool FieldImageProcess(Point fldCenter, CBSEImgClr imageData)
  366. {
  367. return true;
  368. }
  369. public virtual void ClassifyFieldParticles()
  370. {
  371. return;
  372. }
  373. public virtual void ClassifyMergedParticles(List<COTSParticleClr> parts)
  374. {
  375. return;
  376. }
  377. private class AutoResetSEMControl:IDisposable
  378. {
  379. CSmplMeasure sm;
  380. public AutoResetSEMControl(CSmplMeasure s)
  381. {
  382. sm = s;
  383. }
  384. public void Dispose()
  385. {
  386. sm.SetSEMExteralOff();
  387. }
  388. }
  389. public void DoMeasureForOneSample()
  390. {
  391. using (AutoResetSEMControl autoReset = new AutoResetSEMControl(this)) //when this method exit ,the SetSEMExternalOff and ResetScan will be called automatically.
  392. {
  393. // let the main thread to know that this sample measurement starts
  394. var pStatus = m_Sample.GetMsrStatus();
  395. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS);
  396. // set current time to current time
  397. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.START);
  398. // let main App know that the sample begin to measure
  399. ST_MSTMsg MsgSmpStart = new ST_MSTMsg();
  400. MsgSmpStart.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  401. MsgSmpStart.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.INPROCESS;
  402. MsgSmpStart.STMSampleStu.cSampleName = m_Sample.GetName();
  403. m_pMsrThread.SendMessageToMeasureApp(MsgSmpStart);
  404. log.Info(m_Sample.GetName() + " Measurement started!");
  405. // get SEM controller to set magnification and working distance
  406. if (!SetSEMDataMrs())
  407. {
  408. log.Error("DoMeasure: fail to set SEM data.");
  409. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  410. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  411. return;
  412. }
  413. // get SEM external controll on
  414. if (!SetSEMExteralOn())
  415. {
  416. log.Error("DoMeasure: fail to set SEM external.");
  417. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  418. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  419. return;
  420. }
  421. // set the BSE scan param
  422. if (!SetBSEParam())
  423. {
  424. log.Error("DoMeasure: fail to set BSE param.");
  425. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  426. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  427. return;
  428. }
  429. var pSEMDataGnr = new CSEMDataGnr();
  430. log.Info("Get Kv, Brightness and Contrast!");
  431. m_SemHardwareMgr.GetSEMDataGnrFromHw(ref pSEMDataGnr);
  432. m_pSampleRstFile.SetSEMGnr(pSEMDataGnr);
  433. // record SEM data
  434. COTSMsrPrjResultData pProjMgrFile = m_pMsrThread.GetProjResultData();
  435. CSEMStageData pSEMStageData = pProjMgrFile.GetSEMStageData();
  436. m_pSampleRstFile.SetSEMStageData(pSEMStageData);
  437. // record stage
  438. CStage pStage = pProjMgrFile.GetStage();
  439. m_pSampleRstFile.SetSEMStage(pStage);
  440. // calculate field centers
  441. List<System.Drawing.Point> umMeasuredlistFieldCenter;
  442. List<System.Drawing.Point> alllistFieldCenter;
  443. if (!CalculateUnMeasuredFieldsCenters(out alllistFieldCenter,out umMeasuredlistFieldCenter))
  444. {// failed to calculate field centers
  445. log.Error("DoMeasure: failed to calculate field centers.");
  446. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  447. // record end time
  448. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  449. return;
  450. }
  451. //-----save the static measure result file data into xml file and the dynamic data of every field will be saved into sqlite database
  452. log.Info("Create result file!");
  453. if (!m_pSampleRstFile.CreateResultFiles())
  454. {// failed to call measure result file Save method
  455. log.Error("DoMeasure: failed to call measure result file Save method.");
  456. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  457. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  458. return;
  459. }
  460. //------
  461. int nNewFieldId = 0;
  462. int numOfAllFields = pStatus.GetCompletedFields() + umMeasuredlistFieldCenter.Count;//
  463. int completedFields = pStatus.GetCompletedFields();
  464. log.Info("Unmeasured fields:" + umMeasuredlistFieldCenter.Count);
  465. for (int i = 0; i < (int)umMeasuredlistFieldCenter.Count; ++i)
  466. {// check and break if stop button is clicked
  467. if (IsAborted())
  468. {// measure stopped
  469. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.STOPPED);
  470. // record end time
  471. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  472. //must wait for the saving data thread finished,or we'll get null pointer exception when we stop the measure process.
  473. while (fieldQueue.Count() > 0)
  474. {
  475. Thread.Sleep(100);
  476. }
  477. return;
  478. }
  479. // check if sample measurement completes
  480. COTSImgScanPrm pScanParam = m_Sample.GetMsrParams().GetImageScanParam();
  481. int nTotalFieldSize = (int)umMeasuredlistFieldCenter.Count;
  482. if (IsSampleOver(pScanParam, numOfAllFields))
  483. {
  484. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  485. break;
  486. }
  487. // get a field center
  488. System.Drawing.Point poiFieldCentre = umMeasuredlistFieldCenter[i];
  489. // update thread measure status class, let the main thread know that starts a new field
  490. ST_MSTMsg MsgFieldStart = new ST_MSTMsg();
  491. MsgFieldStart.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT;
  492. MsgFieldStart.STMSampleRetData.iRetDataType = MSAMPLE_RET.START_MSR_FIELD;
  493. MsgFieldStart.STMSampleRetData.SMsrField.FieldPos = poiFieldCentre;
  494. m_pMsrThread.SendMessageToMeasureApp(MsgFieldStart);
  495. int fldNo = completedFields + i + 1;
  496. log.Warn("Current field:" + fldNo.ToString());
  497. // move SEM to the field center
  498. if (!MoveSEMToPoint(poiFieldCentre))
  499. {// failed to move SEM to the position
  500. log.Error("DoMeasure: failed to move SEM to the field centre point.");
  501. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  502. // record end time
  503. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  504. return;
  505. }
  506. log.Info("Begin to Acquire BSE image!");
  507. // take BSE image for the fields
  508. CBSEImgClr pBSEImg = AcquireABSEImage();
  509. // let the main thread to know that image process is completed
  510. if (pBSEImg == null)
  511. {
  512. log.Error("ImageProcess: can't get no background image.");
  513. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  514. return;
  515. }
  516. //BSEData
  517. ST_MSTMsg MsgFieldBSE = new ST_MSTMsg();
  518. MsgFieldBSE.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT;
  519. MsgFieldBSE.STMSampleRetData.iRetDataType = MSAMPLE_RET.BSE_DATA;
  520. MsgFieldBSE.STMSampleRetData.BSEData.pos.X = poiFieldCentre.X;
  521. MsgFieldBSE.STMSampleRetData.BSEData.pos.Y = poiFieldCentre.Y;
  522. MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight = pBSEImg.GetHeight();
  523. MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth = pBSEImg.GetWidth();
  524. byte[] pImgData = pBSEImg.GetImageDataPtr();
  525. MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = pImgData;
  526. m_pMsrThread.SendMessageToMeasureApp(MsgFieldBSE);
  527. // get a new field id
  528. log.Info("Acquire BSE image success! Processing image...");
  529. // image process
  530. var rst = FieldImageProcess(poiFieldCentre, pBSEImg);
  531. if (rst == true)
  532. {
  533. // add the field into the field
  534. m_pSampleRstFile.AddAField(curFldData);
  535. }
  536. ++nNewFieldId;
  537. double measuredArea = 0; // this area should be the field area
  538. var a_pBSEImg = curFldData.GetBSEImage();
  539. double dPixelSize = m_Sample.CalculatePixelSize();
  540. measuredArea = a_pBSEImg.GetHeight() * a_pBSEImg.GetWidth()* dPixelSize * dPixelSize + 0.5; //Get measured area
  541. if (!CumulateFieldData(curFldData.GetListAnalysisParticles(), measuredArea))
  542. { // failed to call SaveFieldFile method
  543. log.Error("ImageProcess: call CumulateFieldData method.");
  544. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  545. return;
  546. }
  547. log.Info("Send field data to screen!");
  548. // completed fields
  549. pStatus.SetCompletedFields(pStatus.GetCompletedFields() + 1);
  550. // completed fieldCenter
  551. List<System.Drawing.Point> listCpltedCenter = pStatus.GetCompletedFieldsCenter();
  552. listCpltedCenter.Add(poiFieldCentre);
  553. //Field Data
  554. // record end time
  555. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  556. ST_MSTMsg MsgFieldEnd = new ST_MSTMsg();
  557. MsgFieldEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT;
  558. MsgFieldEnd.STMSampleRetData.iRetDataType = MSAMPLE_RET.FIELD_DATA;
  559. MsgFieldEnd.STMSampleRetData.SFieldData.iCompleteFieldCount = pStatus.GetCompletedFields();
  560. MsgFieldEnd.STMSampleRetData.SFieldData.iMeasureFieldCount = numOfAllFields;
  561. MsgFieldEnd.STMSampleRetData.SFieldData.iSParticleCount = (int)curFldData.GetListAnalysisParticles().Count;
  562. MsgFieldEnd.STMSampleRetData.SFieldData.FieldPos.X = Convert.ToInt32(poiFieldCentre.X);
  563. MsgFieldEnd.STMSampleRetData.SFieldData.FieldPos.Y = Convert.ToInt32(poiFieldCentre.Y);
  564. m_pMsrThread.SendMessageToMeasureApp(MsgFieldEnd);
  565. }
  566. while (bSaveThreadWorking)//wait untill all the field data has been saved.
  567. {
  568. Thread.Sleep(1000);
  569. log.Info("db saving!");
  570. }
  571. //merging particles
  572. log.Info("Merging big particles which are crossing the field edge!");
  573. CImageHandler imgpro = new CImageHandler();
  574. int scanfldsize = m_Sample.GetSEMDataMsr().GetScanFieldSize();
  575. List<COTSParticleClr> mergedParticles = new List<COTSParticleClr>();
  576. double pixelSize = m_Sample.CalculatePixelSize();
  577. imgpro.MergeBigBoundaryParticles(m_pSampleRstFile.GetFieldData(), pixelSize, scanfldsize, m_Sample.GetResolutionSize(), ref mergedParticles);
  578. CalculateMergedPartProperty(mergedParticles,pixelSize);
  579. ClassifyMergedParticles(mergedParticles);
  580. log.Warn("begin particle data db saving...");
  581. SaveMergedParticles(mergedParticles);
  582. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.COMPLT);
  583. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
  584. // let main thread to know that this sample measurement completes
  585. ST_MSTMsg MsgSmplEnd = new ST_MSTMsg();
  586. MsgSmplEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  587. MsgSmplEnd.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.SUCCESSED;
  588. MsgSmplEnd.STMSampleStu.cSampleName = m_Sample.GetName();
  589. m_pMsrThread.SendMessageToMeasureApp(MsgSmplEnd);
  590. }
  591. }
  592. private void CalculateMergedPartProperty(List<COTSParticleClr> mergedParticles,double pixelSize)
  593. {
  594. var m_ImagePro = new CImageHandler();
  595. foreach (COTSParticleClr part in mergedParticles)
  596. {
  597. m_ImagePro.CalParticleImageProp(part, pixelSize);
  598. }
  599. }
  600. public void DoHolePreview(int a_nHoleID)
  601. {
  602. using (AutoResetSEMControl autoReset = new AutoResetSEMControl(this))
  603. {
  604. // let the main thread to know that this sample measurement starts
  605. CMsrSampleStatus pStatus = m_Sample.GetMsrStatus();
  606. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS);
  607. // set current time to current time
  608. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.START);
  609. // let main App know that the sample begin to measure
  610. ST_MSTMsg MsgSmpStart=new ST_MSTMsg();
  611. MsgSmpStart.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  612. MsgSmpStart.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.INPROCESS;
  613. MsgSmpStart.STMSampleStu.cSampleName=m_Sample.GetName();
  614. // get SEM controller to set magnification and working distance
  615. if (!SetSEMDataMrs())
  616. {
  617. log.Error("DoHolePreview: fail to set SEM data.");
  618. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  619. // record end time
  620. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  621. return;
  622. }
  623. // get SEM external controll on
  624. if (!SetSEMExteralOn())
  625. {
  626. log.Error("DoMeasure: fail to set SEM external.");
  627. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  628. // record end time
  629. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  630. return;
  631. }
  632. // set the BSE scan param
  633. if (!SetHoleBSEParam())
  634. {
  635. log.Error("DoMeasure: fail to set BSE param.");
  636. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  637. // record end time
  638. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  639. return;
  640. }
  641. // check if measurement is aborted
  642. if (IsAborted())
  643. {// measurement aborted
  644. log.Trace("DoHolePreview: measurement aborted before get SEM condition.");
  645. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.STOPPED);
  646. // record end time
  647. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  648. return;
  649. }
  650. // calculate field centers
  651. List<System.Drawing.Point> listFieldCenter=new List<System.Drawing.Point>();
  652. List<System.Drawing.Point> alllistFieldCenter = new List<System.Drawing.Point>();
  653. // listFieldCenter.clear();
  654. if (!CalculateUnMeasuredFieldsCenters(out alllistFieldCenter,out listFieldCenter))
  655. {// failed to calculate field centers
  656. log.Error("DoHolePreview: failed to calculate field centers.");
  657. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  658. // record end time
  659. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  660. return;
  661. }
  662. // go through each field
  663. int nNewFieldId = 0;
  664. for ( int i = 0; i < listFieldCenter.Count; ++i)
  665. {// check and break if stop button is clicked
  666. if (IsAborted())
  667. {// measure stopped
  668. log.Trace("DoHolePreview: measure thread is stopped.");
  669. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.STOPPED);
  670. // record end time
  671. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  672. return;
  673. }
  674. // check if sample measurement completes
  675. COTSImgScanPrm pScanParam = m_Sample.GetMsrParams().GetImageScanParam();
  676. int nTotalFieldSize = listFieldCenter.Count;
  677. if (IsSampleOver(pScanParam, nTotalFieldSize))
  678. {
  679. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  680. break;
  681. }
  682. // get a field center
  683. System.Drawing.Point poiFieldCentre = listFieldCenter[i];
  684. // update thread measure status class, let the main thread know that starts a new field
  685. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  686. ST_MSTMsg MsgFieldStart=new ST_MSTMsg();
  687. //memset(&MsgFieldStart, 0, sizeof(ST_MSTMsg));
  688. MsgFieldStart.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT;
  689. MsgFieldStart.STMSampleRetData.iRetDataType = MSAMPLE_RET.START_MSR_FIELD;
  690. MsgFieldStart.STMSampleRetData.SMsrField.FieldPos = poiFieldCentre;
  691. m_pMsrThread.SendMessageToMeasureApp(MsgFieldStart);
  692. // move SEM to the field center
  693. if (!MoveSEMToPoint(poiFieldCentre))
  694. {// failed to move SEM to the position
  695. log.Error("DoHolePreview: failed to move SEM to the field centre point.");
  696. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  697. // record end time
  698. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  699. return;
  700. }
  701. // take BSE image for the fields
  702. CBSEImgClr pBSEIamge = AcquireABSEImage();
  703. if (pBSEIamge==null)
  704. {
  705. // failed to acquire a BSE image
  706. log.Error("DoHolePreview: failed to acquire a BSE image.");
  707. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  708. // record end time
  709. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  710. return;
  711. }
  712. //BSEData
  713. ST_MSTMsg MsgFieldBSE=new ST_MSTMsg();
  714. // memset(&MsgFieldBSE, 0, sizeof(ST_MSTMsg));
  715. MsgFieldBSE.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT;
  716. MsgFieldBSE.STMSampleRetData.iRetDataType = MSAMPLE_RET.BSE_DATA;
  717. MsgFieldBSE.STMSampleRetData.BSEData.pos = poiFieldCentre;
  718. //MsgFieldBSE.STMSampleRetData.BSEData.pos.y = poiFieldCentre.y;
  719. MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight = pBSEIamge.GetHeight();
  720. MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth = pBSEIamge.GetWidth();
  721. byte[] pImgData = pBSEIamge.GetImageDataPtr();
  722. MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = pImgData;
  723. m_pMsrThread.SendMessageToMeasureApp(MsgFieldBSE);
  724. if (pStatus.GetStatus() != OTS_MSR_SAMPLE_STATUS.INPROCESS)
  725. {
  726. // measurement failed or stopped
  727. log.Error("DoHolePreview: measurement failed or stopped.");
  728. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
  729. // record end time
  730. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  731. return;
  732. }
  733. //save the result to project file
  734. CHoleBSEImg pHoleBSEImg =new CHoleBSEImg();
  735. pHoleBSEImg.SetHoleID(a_nHoleID);
  736. pHoleBSEImg.SetPosition(poiFieldCentre);
  737. Rectangle oImageRect =(Rectangle) pBSEIamge.GetImageRect();
  738. int nImageSize = pBSEIamge.GetHeight() * pBSEIamge.GetWidth();
  739. pHoleBSEImg.SetImageRect(oImageRect);
  740. pHoleBSEImg.SetImageData( pBSEIamge.GetImageDataPtr(),oImageRect.Width,oImageRect.Height);
  741. m_listHoleBSEImg.Add(pHoleBSEImg);
  742. COTSMsrPrjResultData pProjMgrFile = m_pMsrThread.GetProjResultData();
  743. pProjMgrFile.SetHoleBESImgList(m_listHoleBSEImg,true);
  744. // prepare for the next
  745. ++nNewFieldId;
  746. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  747. ST_MSTMsg MsgFieldEnd=new ST_MSTMsg();
  748. MsgFieldEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT;
  749. MsgFieldEnd.STMSampleRetData.iRetDataType = MSAMPLE_RET.FIELD_DATA;
  750. MsgFieldEnd.STMSampleRetData.SFieldData.iCompleteFieldCount = (i + 1);
  751. MsgFieldEnd.STMSampleRetData.SFieldData.iMeasureFieldCount = listFieldCenter.Count;
  752. MsgFieldEnd.STMSampleRetData.SFieldData.iSParticleCount = 0;
  753. MsgFieldEnd.STMSampleRetData.SFieldData.FieldPos = poiFieldCentre;
  754. m_pMsrThread.SendMessageToMeasureApp(MsgFieldEnd);
  755. //break;
  756. }
  757. pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
  758. //calculate measure time
  759. pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
  760. // let main thread to know that this sample measurement completes
  761. ST_MSTMsg MsgSmplEnd=new ST_MSTMsg();
  762. MsgSmplEnd.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;
  763. MsgSmplEnd.STMThreadStu.iMsrStatu = OTS_MSR_THREAD_STATUS.COMPLETED;
  764. m_pMsrThread.SendMessageToMeasureApp(MsgSmplEnd);
  765. }
  766. }
  767. // Cumulate field data info
  768. public virtual bool CumulateFieldData( List<COTSParticleClr> listParticles, double a_nMeasuredArea)
  769. {
  770. // get measure result items of the sample
  771. CMsrDisplayResults pMsrResults = m_Sample.GetMsrResults();
  772. // cumulate field data info
  773. //pMsrResults.CumulateMeasureResults(listResultItems);
  774. pMsrResults.CumulateMeasuredArea(a_nMeasuredArea);
  775. // cumulate ratio
  776. double dRatio = 10000 * pMsrResults.GetTotalParticleArea();
  777. dRatio = dRatio / pMsrResults.GetMeasuredArea();
  778. pMsrResults.SetRatio(dRatio);
  779. // go through the particles list
  780. foreach (COTSParticleClr pParticle in listParticles)
  781. {
  782. // create a measure result item
  783. pMsrResults.CumulateMeasureResult(pParticle);
  784. }
  785. // ok, return TRUE
  786. return true;
  787. }
  788. // hole BSE images list
  789. void SetHoleBESImgList(CHoleBSEImgsList a_listHoleBSEImg, bool a_bClear/* = TRUE*/)
  790. {// clear the hole BSE image list if necessary
  791. if (a_bClear)
  792. {
  793. m_listHoleBSEImg.Clear();
  794. }
  795. // go through the input list
  796. foreach (var pHoleBSEImg in a_listHoleBSEImg)
  797. {// add the new hole BSE image into HoleBSEImage list
  798. m_listHoleBSEImg.Add(pHoleBSEImg);
  799. }
  800. }
  801. public bool SaveMergedParticles(List<COTSParticleClr> mergedParts)
  802. {
  803. CIncAFileMgr pDBFileMgr = m_pSampleRstFile.DBFileMgr;
  804. var mergedpartdb = pDBFileMgr.GetMergedParticleDB();
  805. foreach (COTSParticleClr part in mergedParts)
  806. {
  807. mergedpartdb.SaveAParticle(part, part.GetXray(), (Point)part.GetAbsolutPos());
  808. }
  809. CPosXrayDBMgr pXrayDBMgr = pDBFileMgr.GetPosXrayDBMgr();
  810. CElementChemistryDB xraydb = pXrayDBMgr.GetElementChemistryDB();
  811. List<CPosXrayClr> ches = new List<CPosXrayClr>();
  812. foreach (COTSParticleClr part in mergedParts)
  813. {
  814. ches.Add(part.GetXray());
  815. }
  816. xraydb.SaveElementChemistriesList(ches);
  817. return true;
  818. }
  819. }
  820. }