CSmplMeasure.cs 38 KB

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