CMeasure.cs 17 KB

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