CMeasure.cs 18 KB

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