CMeasure.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. using System.Collections.Generic;
  2. using OTSDataType;
  3. using System;
  4. using System.Drawing;
  5. using static OTSDataType.otsdataconst;
  6. using OTSModelSharp.ImageProcess;
  7. using OTSModelSharp.ServiceCenter;
  8. using System.Threading;
  9. using OTSCLRINTERFACE;
  10. using OTSMeasureApp._1_OTSMeasure.Measure._3_MeasureFlow;
  11. namespace OTSModelSharp
  12. {
  13. // enum and struct used for send message to App
  14. public class CMeasure
  15. {
  16. private const string UNTITLED_FILE_NAME = "Untitled";
  17. public delegate void ProgressEventHandler(ST_MSTMsg msg);
  18. public event ProgressEventHandler ProgressEvent;
  19. public event ProgressEventHandler HolePreviewEvent;
  20. COTSMsrPrjResultData m_pProjData;
  21. List< COTSSample> m_listMeasurableSamples=new List<COTSSample>();
  22. string m_strWorkingFolder;
  23. readonly CMsrThreadStatus m_ThreadStatus;
  24. readonly ISemController m_SemController;
  25. protected static NLog.Logger loger = NLog.LogManager.GetCurrentClassLogger();
  26. public SortedDictionary<string, CSmplMeasure> mapSmplMsr = new SortedDictionary<string, CSmplMeasure>();//use this map to hold all the smplMeasure object
  27. public List<COTSSample> GetListMeasurableSamples()
  28. {
  29. return m_listMeasurableSamples;
  30. }
  31. public void SetListMeasurableSamples(List<COTSSample> value)
  32. {
  33. m_listMeasurableSamples = value;
  34. }
  35. public CMeasure()
  36. {
  37. m_strWorkingFolder = "";
  38. m_ThreadStatus = new CMsrThreadStatus();
  39. m_SemController = SemController.GetSEMController();
  40. }
  41. public COTSMsrPrjResultData GetProjResultData()
  42. {
  43. return m_pProjData;
  44. }
  45. public ISemController GetSEMController()
  46. {
  47. // get SEM, scanner and x-ray controller via hardware manager
  48. return m_SemController;
  49. }
  50. public CMsrThreadStatus GetMsrThreadStatus() { return m_ThreadStatus; }
  51. public void Init(COTSMsrPrjResultData a_pProjMgrFile)
  52. {
  53. m_pProjData = a_pProjMgrFile;
  54. SetListMeasurableSamples(a_pProjMgrFile.GetSampleList());
  55. return ;
  56. }
  57. void ThreadOver()
  58. {
  59. ST_MSTMsg MsrMsg = new ST_MSTMsg(m_ThreadStatus);
  60. MsrMsg.InitThreadOverMsg();
  61. SendMessageToMeasureGUI(MsrMsg);
  62. if (m_ThreadStatus.GetStatus() == otsdataconst.OTS_MSR_THREAD_STATUS.FAILED || m_ThreadStatus.GetStatus() == otsdataconst.OTS_MSR_THREAD_STATUS.COMPLETED)
  63. {
  64. if (m_pProjData.GetGenParam().AutoBeamOff)
  65. {
  66. m_SemController.SetSemBeamBlank(false); //true?
  67. }
  68. }
  69. }
  70. void HolePreviewThreadOver()
  71. {
  72. ST_MSTMsg MsrMsg = new ST_MSTMsg(m_ThreadStatus);
  73. MsrMsg.InitThreadOverMsg();
  74. SendHolePreviewMessageToMeasureGUI(MsrMsg);
  75. }
  76. void SetWorkingFolderStrAndSaveCurrentSettings()
  77. {
  78. // get project file pathname
  79. string strSettingFilePathName = m_pProjData.GetPathName();
  80. strSettingFilePathName.Trim();
  81. if (strSettingFilePathName == "")
  82. {
  83. loger .Error("SetWorkingFolderStr: project file pathname is an empty string");
  84. return ;
  85. }
  86. else if (strSettingFilePathName==UNTITLED_FILE_NAME)
  87. {
  88. loger .Error ("SetWorkingFolderStr: project file pathname is an invalid string");
  89. return ;
  90. }
  91. // working folder string
  92. m_strWorkingFolder = FileHelper.GetFolderName(strSettingFilePathName);
  93. m_pProjData.Save();
  94. return ;
  95. }
  96. public void SendMessageToMeasureGUI(ST_MSTMsg msg)
  97. {
  98. ProgressEvent(msg);
  99. }
  100. public void SendHolePreviewMessageToMeasureGUI(ST_MSTMsg msg)
  101. {
  102. HolePreviewEvent(msg);
  103. }
  104. public bool IsMeasureStopped()
  105. {
  106. return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.STOPPED;
  107. }
  108. public bool IsMeasureRunning() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.INPROCESS; }
  109. public bool IsMeasureFailed() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.FAILED; }
  110. public bool IsMeasureCompleted() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.COMPLETED; }
  111. public void DoMeasure()
  112. {
  113. // start measurement, creat thread measure status class, let the main thread know that measurement started
  114. m_ThreadStatus.SetStartTime(System.DateTime.Now);
  115. ST_MSTMsg MsgMsrStart = new ST_MSTMsg(m_ThreadStatus);
  116. MsgMsrStart.InitThreadStartMsg();
  117. SendMessageToMeasureGUI (MsgMsrStart);
  118. loger.Info("Measurement started!");
  119. // connect hardware
  120. loger.Info("Connect SEM!");
  121. if (!m_SemController.Connect())
  122. {
  123. loger .Error("DoMeasure: failed to connect hardware.");
  124. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.FAILED);
  125. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  126. ThreadOver();
  127. return;
  128. }
  129. // set working directory which is the same directory of the setting file
  130. SetWorkingFolderStrAndSaveCurrentSettings();
  131. List <string > listMeasuredSamples = m_ThreadStatus.GetCompletedSamples();
  132. // got through measure list
  133. foreach (var pSample in GetListMeasurableSamples())
  134. {// check and break if stop button is clicked
  135. if (m_ThreadStatus.GetStatus()== OTS_MSR_THREAD_STATUS.STOPPED )
  136. {
  137. // stop button clicked
  138. loger .Info("DoMeasure: stop button is clicked.");
  139. // record end time
  140. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  141. ThreadOver();
  142. return;
  143. }
  144. if (m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.PAUSED)
  145. {
  146. // stop button clicked
  147. loger.Info("DoMeasure: stop button is clicked.");
  148. // record end time
  149. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  150. while (m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.PAUSED)
  151. {
  152. Thread.Sleep(300);
  153. }
  154. //return;
  155. }
  156. if (!pSample.GetSwitch())
  157. {
  158. continue;
  159. }
  160. var sta = pSample.GetMsrStatus().GetStatus();
  161. if (sta == OTS_MSR_SAMPLE_STATUS.SUCCESSED || sta == OTS_MSR_SAMPLE_STATUS.STOPPED)
  162. {
  163. continue;
  164. }
  165. CSmplMeasure pSmplMeasure;
  166. if (!mapSmplMsr.ContainsKey(pSample.GetName()))
  167. {// create a sample measure object for the sample
  168. switch (m_pProjData.SystemTypeId)
  169. {
  170. case OTS_SysType_ID.IncA:
  171. pSmplMeasure = new CSmplMeasureIncA(m_strWorkingFolder, pSample);
  172. break;
  173. case OTS_SysType_ID.CleannessA:
  174. pSmplMeasure = new CSmplMeasureCleanliness(m_strWorkingFolder, pSample);
  175. break;
  176. default:
  177. pSmplMeasure = new CSmplMeasureIncA(m_strWorkingFolder, pSample);
  178. break;
  179. }
  180. // set measure thread
  181. pSmplMeasure.SetMsrThread(this);
  182. mapSmplMsr[pSample.GetName()] = pSmplMeasure;
  183. }
  184. else
  185. {
  186. pSmplMeasure = mapSmplMsr[pSample.GetName()];
  187. pSample.GetMsrStatus().SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS);
  188. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.INPROCESS);
  189. }
  190. m_pProjData.SetWorkingSampleByName(pSample.GetName());
  191. pSmplMeasure.DoMeasureForOneSample();
  192. if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.STOPPED)
  193. {// record end time
  194. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.STOPPED);
  195. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  196. // update thread measure status class, let the main thread know that this sample measurement stopped
  197. ST_MSTMsg MsgSmpStop = new ST_MSTMsg(m_ThreadStatus);
  198. MsgSmpStop.InitThreadStoppedMsg();
  199. SendMessageToMeasureGUI(MsgSmpStop);
  200. ThreadOver();
  201. break;
  202. }
  203. if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.FAILED)
  204. {
  205. // measurement failed
  206. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.FAILED);
  207. // record end time
  208. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  209. // update thread measure status class, let the main thread know that this sample measurement failed
  210. ST_MSTMsg MsgSmpFailed=new ST_MSTMsg(m_ThreadStatus);
  211. MsgSmpFailed.InitThreadFailedMsg();
  212. SendMessageToMeasureGUI(MsgSmpFailed);
  213. ThreadOver();
  214. return;
  215. }
  216. // update thread measure status class, let the main thread know that this sample measurement successes
  217. ST_MSTMsg MsgSmpSuccess = new ST_MSTMsg(m_ThreadStatus);
  218. MsgSmpSuccess.InitThreadSucceedMsg();
  219. SendMessageToMeasureGUI(MsgSmpSuccess);
  220. // continue to the next sample
  221. listMeasuredSamples.Add(pSample.GetName());
  222. }
  223. // measurement completed
  224. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.COMPLETED);
  225. // record end time
  226. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  227. ThreadOver();
  228. }
  229. // hole preview
  230. public void DoHolePreview()
  231. {
  232. // start measurement, creat thread measure status class, let the main thread know that measurement started
  233. // set measure status to in-process
  234. //record time
  235. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.START);
  236. DateTime timeStart = m_ThreadStatus.GetStartTime();
  237. ST_MSTMsg MsgMsrStart = new ST_MSTMsg(m_ThreadStatus);
  238. MsgMsrStart.InitHolePreThreadInProcessMsg();
  239. SendHolePreviewMessageToMeasureGUI(MsgMsrStart);
  240. // connect hardware
  241. if (!m_SemController.Connect())
  242. {
  243. // failed to connect hardware
  244. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.FAILED);
  245. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  246. HolePreviewThreadOver();
  247. }
  248. var a_pMeasureArea = m_pProjData.GetWorkingSample().GetMsrDomain();
  249. COTSSample pSampleHole = CreateHoleSample(a_pMeasureArea);
  250. // create a sample measure object for the sample
  251. CSmplMeasure pSmplMeasure = new CSmplMeasure(m_strWorkingFolder, m_pProjData.GetWorkingSample());
  252. // set measure thread
  253. pSmplMeasure.SetMsrThread(this);
  254. // update thread measure status class, let the main thread know that this sample measurement starts
  255. pSmplMeasure.SetHolePreviewSample(pSampleHole);
  256. // do measure
  257. pSmplMeasure.DoHolePreview();
  258. // check if measurement is successful
  259. if (pSampleHole.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.STOPPED)
  260. {
  261. // record end time
  262. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  263. // measurement stopped
  264. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.STOPPED);
  265. // update thread measure status class, let the main thread know that this sample measurement stopped
  266. ST_MSTMsg MsgSmpStop = new ST_MSTMsg(m_ThreadStatus);
  267. MsgSmpStop.InitHolePreThreadStoppedMsg();
  268. SendHolePreviewMessageToMeasureGUI(MsgSmpStop);
  269. HolePreviewThreadOver();
  270. return;
  271. }
  272. else if (pSampleHole.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.FAILED)
  273. {
  274. // measurement failed
  275. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.FAILED);
  276. // record end time
  277. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  278. // update thread measure status class, let the main thread know that this sample measurement failed
  279. ST_MSTMsg MsgSmpFailed = new ST_MSTMsg(m_ThreadStatus);
  280. MsgSmpFailed.InitHolePreThreadFailedMsg();
  281. SendHolePreviewMessageToMeasureGUI(MsgSmpFailed);
  282. HolePreviewThreadOver();
  283. return;
  284. }
  285. // record end time
  286. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  287. // update thread measure status class, let the main thread know that this sample measurement successes
  288. ST_MSTMsg MsgSmpSuccess = new ST_MSTMsg(m_ThreadStatus);
  289. MsgSmpSuccess.InitHolePreThreadSucceedMsg();
  290. SendHolePreviewMessageToMeasureGUI(MsgSmpSuccess);
  291. // measurement completed
  292. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.COMPLETED);
  293. // record end time
  294. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  295. HolePreviewThreadOver();
  296. }
  297. public COTSSample CreateHoleSample(CDomain a_pMsrArea)
  298. {
  299. COTSSample pHoleSample = new COTSSample();
  300. pHoleSample.SetMsrDomain(a_pMsrArea);
  301. // get min magnification
  302. CSEMStageData pSEMStageData = m_pProjData.GetSEMStageData();
  303. double dMinMag = pSEMStageData.GetMinMag();
  304. // get scan field size 100
  305. int nScanFieldSize100 = pSEMStageData.GetScanFieldSize100();
  306. // get working distance
  307. double dWorkingDistance = 0.0;
  308. if (!GetSEMWorkingDistanceFromHW(ref dWorkingDistance))
  309. {
  310. return null;
  311. }
  312. CSEMDataMsr poSEMDataMsr = new CSEMDataMsr();
  313. poSEMDataMsr.SetScanFieldSize100(nScanFieldSize100);
  314. poSEMDataMsr.SetWorkingDistance(dWorkingDistance);
  315. poSEMDataMsr.SetMagnification(dMinMag);
  316. pHoleSample.SetSEMDataMsr(poSEMDataMsr);
  317. // Set image scan param
  318. COTSImgScanPrm poImageScanParam = new COTSImgScanPrm();
  319. poImageScanParam.SetStopMode(((int)OTS_MEASURE_STOP_MODE.CoverMode).ToString());
  320. poImageScanParam.SetStartImageMode(OTS_GET_IMAGE_MODE.Zshape);
  321. poImageScanParam.SetScanImageSpeed(OTS_IMAGE_SCANSPEED_OPTIONS.low);
  322. CSampleParam poMsrParams = pHoleSample.GetMsrParams();
  323. poImageScanParam.SetImageResulotion(GetListMeasurableSamples()[0].GetMsrParams().GetImageScanParam().GetImageResulotion());//由于各样品分辨率应该一致,故此处没有读取选取的特定样品孔样品
  324. poMsrParams.SetImageScanParam(poImageScanParam);
  325. pHoleSample.SetMsrParams(poMsrParams);
  326. return pHoleSample;
  327. }
  328. public bool GetSEMWorkingDistanceFromHW(ref double a_dWorkingDistance)
  329. {
  330. m_SemController.GetWorkingDistance(ref a_dWorkingDistance);
  331. return true;
  332. }
  333. // measure status
  334. public void SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS a_nMsrLoopStatus)
  335. {
  336. m_ThreadStatus.SetStatus( a_nMsrLoopStatus);
  337. }
  338. }
  339. }