CSmplMeasure.cs 38 KB

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