CMeasure.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  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. namespace OTSModelSharp
  10. {
  11. // enum and struct used for send message to App
  12. public enum ENUM_MSG_TYPE
  13. {
  14. MTHREADSTATUS = 1001,
  15. MSAMPLESTATUS = 1002,
  16. MSAMPLERESULT = 1003
  17. };
  18. public enum MSAMPLE_RET
  19. {
  20. BSE_DATA = 0,
  21. FIELD_DATA = 1,
  22. START_MSR_FIELD = 2
  23. };
  24. public struct SMSR_COMPLETE_DATA
  25. {
  26. public OTS_MSR_THREAD_STATUS MsrStatus;
  27. public string csMsrStartTime;
  28. public int iMsrCompleteSampleCount;
  29. public int iMsrCompleteFieldCount;
  30. public int iParticleCount;
  31. public TimeSpan MsrUsedTime;
  32. public string csMsrEndTime;
  33. };
  34. public struct STMThreadStatus
  35. {
  36. public OTS_MSR_THREAD_STATUS iMsrStatu; //OTS_MSR_THREAD_STATUS
  37. public string csMsrStartTime; //MSR_START_TIME
  38. public string csMsrEndTime; //MSR_END_TIME
  39. public SMSR_COMPLETE_DATA SMsrCompleteData;
  40. };
  41. public struct STMSampleStatus
  42. {
  43. public OTS_MSR_SAMPLE_STATUS iMsrSampleStatu; //OTS_MSR_SAMPLE_STATUS
  44. public string cSampleName;
  45. public string csSampleMsrStartTime;
  46. public List<PointF> BCompleteFieldList;
  47. };
  48. public struct STMSampleResultData
  49. {
  50. public MSAMPLE_RET iRetDataType; //ENUM_MEASURE_SAMPLE_RESULT
  51. public struct RBSEDATA
  52. {
  53. public int fieldId;
  54. public System.Drawing.Point pos;
  55. public int iBSEDataHeight;
  56. public int iBSEDataWidth;
  57. public byte[] lpBSEData;
  58. };
  59. public struct SAMPLEFIELDDATA
  60. {
  61. public System.Drawing.Point FieldPos;
  62. public int iMeasureFieldCount;
  63. public int iCompleteFieldCount;
  64. public int iSParticleCount; // Field particle count
  65. public TimeSpan TUsedTime;
  66. };
  67. public struct StartToMsrField
  68. {
  69. public System.Drawing.Point FieldPos;
  70. };
  71. public RBSEDATA BSEData;
  72. public SAMPLEFIELDDATA SFieldData;
  73. public StartToMsrField SMsrField;
  74. };
  75. public struct ST_MSTMsg
  76. {
  77. public ENUM_MSG_TYPE iMsgType;
  78. public STMThreadStatus STMThreadStu;
  79. public STMSampleStatus STMSampleStu;
  80. public STMSampleResultData STMSampleRetData;
  81. };
  82. public class CMeasure
  83. {
  84. private const string UNTITLED_FILE_NAME = "Untitled";
  85. public delegate void ProgressEventHandler(ST_MSTMsg msg);
  86. public event ProgressEventHandler ProgressEvent;
  87. COTSMsrPrjResultData m_pProjData;
  88. List< COTSSample> m_listMeasurableSamples=new List<COTSSample>();
  89. string m_strWorkingFolder;
  90. readonly CMsrThreadStatus m_ThreadStatus;
  91. readonly ISemController m_SemController;
  92. protected static NLog.Logger loger = NLog.LogManager.GetCurrentClassLogger();
  93. public SortedDictionary<string, CSmplMeasure> mapSmplMsr = new SortedDictionary<string, CSmplMeasure>();//use this map to hold all the smplMeasure object
  94. public List<COTSSample> GetListMeasurableSamples()
  95. {
  96. return m_listMeasurableSamples;
  97. }
  98. public void SetListMeasurableSamples(List<COTSSample> value)
  99. {
  100. m_listMeasurableSamples = value;
  101. }
  102. public CMeasure()
  103. {
  104. m_strWorkingFolder = "";
  105. m_ThreadStatus = new CMsrThreadStatus();
  106. m_SemController = SemController.GetSEMController();
  107. }
  108. public COTSMsrPrjResultData GetProjResultData()
  109. {
  110. return m_pProjData;
  111. }
  112. public ISemController GetSEMController()
  113. {
  114. // get SEM, scanner and x-ray controller via hardware manager
  115. return m_SemController;
  116. }
  117. public CMsrThreadStatus GetMsrThreadStatus() { return m_ThreadStatus; }
  118. public void Init(COTSMsrPrjResultData a_pProjMgrFile)
  119. {
  120. m_pProjData = a_pProjMgrFile;
  121. SetListMeasurableSamples(a_pProjMgrFile.GetSampleList());
  122. return ;
  123. }
  124. void ThreadOver()
  125. {
  126. DateTime timeEnd = m_ThreadStatus.GetEndTime();
  127. ST_MSTMsg MsrMsg = new ST_MSTMsg
  128. {
  129. iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS
  130. };
  131. MsrMsg.STMThreadStu.iMsrStatu = m_ThreadStatus.GetStatus();
  132. MsrMsg.STMThreadStu.csMsrEndTime = timeEnd.ToString("yyyy-MM-dd HH:mm:ss");
  133. ProgressEvent(MsrMsg);
  134. if (MsrMsg.STMThreadStu.iMsrStatu == otsdataconst.OTS_MSR_THREAD_STATUS.FAILED || MsrMsg.STMThreadStu.iMsrStatu == otsdataconst.OTS_MSR_THREAD_STATUS.COMPLETED)
  135. {
  136. if (m_pProjData.GetGenParam().AutoBeamOff)
  137. {
  138. m_SemController.SetSemBeamCurrent(false); //true?
  139. }
  140. }
  141. }
  142. void ThreadOverWithoutDisConnect()
  143. {
  144. DateTime timeEnd = m_ThreadStatus.GetEndTime();
  145. ST_MSTMsg MsrMsg = new ST_MSTMsg();
  146. MsrMsg.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;
  147. MsrMsg.STMThreadStu.iMsrStatu = m_ThreadStatus.GetStatus();
  148. MsrMsg.STMThreadStu.csMsrEndTime = timeEnd.ToString("yyyy-MM-dd HH:mm:ss");
  149. ProgressEvent(MsrMsg);
  150. }
  151. void SetWorkingFolderStrAndSaveCurrentSettings()
  152. {
  153. // get project file pathname
  154. string strSettingFilePathName = m_pProjData.GetPathName();
  155. strSettingFilePathName.Trim();
  156. if (strSettingFilePathName == "")
  157. {
  158. loger .Error("SetWorkingFolderStr: project file pathname is an empty string");
  159. return ;
  160. }
  161. else if (strSettingFilePathName==UNTITLED_FILE_NAME)
  162. {
  163. loger .Error ("SetWorkingFolderStr: project file pathname is an invalid string");
  164. return ;
  165. }
  166. // working folder string
  167. m_strWorkingFolder = FileHelper.GetFolderName(strSettingFilePathName);
  168. m_pProjData.Save();
  169. return ;
  170. }
  171. public void SendMessageToMeasureApp(ST_MSTMsg msg)
  172. {
  173. ProgressEvent(msg);
  174. }
  175. public bool IsMeasureStopped()
  176. {
  177. return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.STOPPED;
  178. }
  179. public bool IsMeasureRunning() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.INPROCESS; }
  180. public bool IsMeasureFailed() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.FAILED; }
  181. public bool IsMeasureCompleted() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.COMPLETED; }
  182. public void DoMeasure()
  183. {
  184. // start measurement, creat thread measure status class, let the main thread know that measurement started
  185. m_ThreadStatus.SetStartTime(System.DateTime.Now);
  186. DateTime timeStart = m_ThreadStatus.GetStartTime();
  187. ST_MSTMsg MsgMsrStart = new ST_MSTMsg
  188. {
  189. iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS
  190. };
  191. MsgMsrStart.STMThreadStu.iMsrStatu = OTS_MSR_THREAD_STATUS.INPROCESS;
  192. MsgMsrStart.STMThreadStu.csMsrStartTime = timeStart.ToShortDateString();
  193. ProgressEvent (MsgMsrStart);
  194. loger.Info("Measurement started!");
  195. // connect hardware
  196. loger.Info("Connect SEM!");
  197. if (!m_SemController.Connect())
  198. {
  199. loger .Error("DoMeasure: failed to connect hardware.");
  200. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.FAILED);
  201. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  202. ThreadOver();
  203. return;
  204. }
  205. // set working directory which is the same directory of the setting file
  206. SetWorkingFolderStrAndSaveCurrentSettings();
  207. List <string > listMeasuredSamples = m_ThreadStatus.GetCompletedSamples();
  208. // got through measure list
  209. foreach (var pSample in GetListMeasurableSamples())
  210. {// check and break if stop button is clicked
  211. if (m_ThreadStatus.GetStatus()== OTS_MSR_THREAD_STATUS.STOPPED )
  212. {
  213. // stop button clicked
  214. loger .Info("DoMeasure: stop button is clicked.");
  215. // record end time
  216. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  217. ThreadOver();
  218. return;
  219. }
  220. if (m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.PAUSED)
  221. {
  222. // stop button clicked
  223. loger.Info("DoMeasure: stop button is clicked.");
  224. // record end time
  225. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  226. while (m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.PAUSED)
  227. {
  228. Thread.Sleep(300);
  229. }
  230. //return;
  231. }
  232. if (!pSample.GetSwitch())
  233. {
  234. continue;
  235. }
  236. var sta = pSample.GetMsrStatus().GetStatus();
  237. if (sta == OTS_MSR_SAMPLE_STATUS.SUCCESSED || sta == OTS_MSR_SAMPLE_STATUS.STOPPED)
  238. {
  239. continue;
  240. }
  241. CSmplMeasure pSmplMeasure;
  242. if (!mapSmplMsr.ContainsKey(pSample.GetName()))
  243. {// create a sample measure object for the sample
  244. switch (m_pProjData.SystemTypeId)
  245. {
  246. case OTS_SysType_ID.IncA:
  247. pSmplMeasure = new CSmplMeasureInclution(m_strWorkingFolder, pSample);
  248. break;
  249. case OTS_SysType_ID.CleannessA:
  250. pSmplMeasure = new CSmplMeasureCleanliness(m_strWorkingFolder, pSample);
  251. break;
  252. default:
  253. pSmplMeasure = new CSmplMeasureInclution(m_strWorkingFolder, pSample);
  254. break;
  255. }
  256. // set measure thread
  257. pSmplMeasure.SetMsrThread(this);
  258. mapSmplMsr[pSample.GetName()] = pSmplMeasure;
  259. }
  260. else
  261. {
  262. pSmplMeasure = mapSmplMsr[pSample.GetName()];
  263. pSample.GetMsrStatus().SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS);
  264. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.INPROCESS);
  265. }
  266. pSmplMeasure.DoMeasureForOneSample();
  267. // check if measurement is successful
  268. if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.PAUSED)
  269. {// record end time
  270. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.PAUSED);
  271. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  272. // update thread measure status class, let the main thread know that this sample measurement stopped
  273. ST_MSTMsg MsgSmpStop = new ST_MSTMsg();
  274. MsgSmpStop.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  275. MsgSmpStop.STMThreadStu.iMsrStatu = OTS_MSR_THREAD_STATUS.PAUSED;
  276. MsgSmpStop.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.PAUSED;
  277. MsgSmpStop.STMThreadStu.csMsrEndTime = DateTime.Now.ToShortDateString();
  278. MsgSmpStop.STMThreadStu.iMsrStatu = OTS_MSR_THREAD_STATUS.PAUSED;
  279. ProgressEvent(MsgSmpStop);
  280. ThreadOver();
  281. return;
  282. }else if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.STOPPED)
  283. {// record end time
  284. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.STOPPED);
  285. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  286. // update thread measure status class, let the main thread know that this sample measurement stopped
  287. ST_MSTMsg MsgSmpStop = new ST_MSTMsg();
  288. MsgSmpStop.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  289. MsgSmpStop.STMThreadStu.iMsrStatu= OTS_MSR_THREAD_STATUS.STOPPED;
  290. MsgSmpStop.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.STOPPED;
  291. MsgSmpStop.STMThreadStu.csMsrEndTime = DateTime .Now .ToShortDateString();
  292. MsgSmpStop.STMThreadStu.iMsrStatu= OTS_MSR_THREAD_STATUS.STOPPED;
  293. ProgressEvent(MsgSmpStop);
  294. ThreadOver();
  295. break;
  296. }
  297. else if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.FAILED)
  298. {
  299. // measurement failed
  300. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.FAILED);
  301. // record end time
  302. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  303. // update thread measure status class, let the main thread know that this sample measurement failed
  304. ST_MSTMsg MsgSmpFailed=new ST_MSTMsg();
  305. MsgSmpFailed.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  306. MsgSmpFailed.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.FAILED;
  307. ProgressEvent(MsgSmpFailed);
  308. ThreadOver();
  309. return;
  310. }
  311. // update thread measure status class, let the main thread know that this sample measurement successes
  312. ST_MSTMsg MsgSmpSuccess = new ST_MSTMsg();
  313. MsgSmpSuccess.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  314. MsgSmpSuccess.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.SUCCESSED;
  315. ProgressEvent(MsgSmpSuccess);
  316. // continue to the next sample
  317. listMeasuredSamples.Add(pSample.GetName());
  318. }
  319. // measurement completed
  320. m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.COMPLETED);
  321. // record end time
  322. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  323. ThreadOver();
  324. }
  325. // hole preview
  326. public void DoHolePreview()
  327. {
  328. // start measurement, creat thread measure status class, let the main thread know that measurement started
  329. // set measure status to in-process
  330. //record time
  331. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.START);
  332. DateTime timeStart = m_ThreadStatus.GetStartTime();
  333. ST_MSTMsg MsgMsrStart = new ST_MSTMsg();
  334. MsgMsrStart.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;
  335. MsgMsrStart.STMThreadStu.iMsrStatu =OTS_MSR_THREAD_STATUS.INPROCESS;
  336. SendMessageToMeasureApp(MsgMsrStart);
  337. // connect hardware
  338. if (!m_SemController.Connect())
  339. {
  340. // failed to connect hardware
  341. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.FAILED);
  342. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  343. ThreadOverWithoutDisConnect();
  344. }
  345. var a_pMeasureArea = m_pProjData.GetWorkingSample().GetMsrDomain();
  346. COTSSample pSampleHole = CreateHoleSample(a_pMeasureArea);
  347. // create a sample measure object for the sample
  348. CSmplMeasure pSmplMeasure = new CSmplMeasure(m_strWorkingFolder, m_pProjData.GetWorkingSample());
  349. // set measure thread
  350. pSmplMeasure.SetMsrThread(this);
  351. // update thread measure status class, let the main thread know that this sample measurement starts
  352. // set working folder string
  353. pSmplMeasure.SetHolePreviewSample(pSampleHole);
  354. pSmplMeasure.SetWorkingFolder(m_strWorkingFolder);
  355. // do measure
  356. pSmplMeasure.DoHolePreview();
  357. // check if measurement is successful
  358. if (pSampleHole.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.STOPPED)
  359. {
  360. // record end time
  361. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  362. // measurement stopped
  363. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.STOPPED);
  364. // update thread measure status class, let the main thread know that this sample measurement stopped
  365. ST_MSTMsg MsgSmpStop = new ST_MSTMsg();
  366. MsgSmpStop.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  367. MsgSmpStop.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.STOPPED;
  368. SendMessageToMeasureApp(MsgSmpStop);
  369. ThreadOverWithoutDisConnect();
  370. return;
  371. }
  372. else if (pSampleHole.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.FAILED)
  373. {
  374. // measurement failed
  375. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.FAILED);
  376. // record end time
  377. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  378. // update thread measure status class, let the main thread know that this sample measurement failed
  379. ST_MSTMsg MsgSmpFailed = new ST_MSTMsg();
  380. MsgSmpFailed.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  381. MsgSmpFailed.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.FAILED;
  382. SendMessageToMeasureApp(MsgSmpFailed);
  383. ThreadOverWithoutDisConnect();
  384. return;
  385. }
  386. // record end time
  387. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  388. // update thread measure status class, let the main thread know that this sample measurement successes
  389. ST_MSTMsg MsgSmpSuccess = new ST_MSTMsg();
  390. MsgSmpSuccess.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
  391. MsgSmpSuccess.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.SUCCESSED;
  392. SendMessageToMeasureApp(MsgSmpSuccess);
  393. // measurement completed
  394. SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.COMPLETED);
  395. // record end time
  396. m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
  397. ThreadOverWithoutDisConnect();
  398. }
  399. public COTSSample CreateHoleSample(CDomain a_pMsrArea)
  400. {
  401. COTSSample pHoleSample = new COTSSample();
  402. pHoleSample.SetMsrDomain(a_pMsrArea);
  403. // get min magnification
  404. CSEMStageData pSEMStageData = m_pProjData.GetSEMStageData();
  405. double dMinMag = pSEMStageData.GetMinMag();
  406. // get scan field size 100
  407. int nScanFieldSize100 = pSEMStageData.GetScanFieldSize100();
  408. // get working distance
  409. double dWorkingDistance = 0.0;
  410. if (!GetSEMWorkingDistanceFromHW(ref dWorkingDistance))
  411. {
  412. return null;
  413. }
  414. CSEMDataMsr poSEMDataMsr = new CSEMDataMsr();
  415. poSEMDataMsr.SetScanFieldSize100(nScanFieldSize100);
  416. poSEMDataMsr.SetWorkingDistance(dWorkingDistance);
  417. poSEMDataMsr.SetMagnification(dMinMag);
  418. pHoleSample.SetSEMDataMsr(poSEMDataMsr);
  419. // Set image scan param
  420. COTSImgScanPrm poImageScanParam = new COTSImgScanPrm();
  421. poImageScanParam.SetStopMode(((int)OTS_MEASURE_STOP_MODE.CoverMode).ToString());
  422. poImageScanParam.SetStartImageMode(OTS_GET_IMAGE_MODE.FROM_CENTER);
  423. poImageScanParam.SetScanImageSpeed(OTS_IMAGE_SCANSPEED_OPTIONS.low);
  424. //poImageScanParam.SetImagePixelSize(OTS_FIVE_TIES_OPTIONS.TIE1);
  425. CSampleParam poMsrParams = pHoleSample.GetMsrParams();
  426. poImageScanParam.SetImageResulotion(GetListMeasurableSamples()[0].GetMsrParams().GetImageScanParam().GetImageResulotion());//由于各样品分辨率应该一致,故此处没有读取选取的特定样品孔样品
  427. poMsrParams.SetImageScanParam(poImageScanParam);
  428. pHoleSample.SetMsrParams(poMsrParams);
  429. return pHoleSample;
  430. }
  431. public bool GetSEMWorkingDistanceFromHW(ref double a_dWorkingDistance)
  432. {
  433. m_SemController.GetWorkingDistance(ref a_dWorkingDistance);
  434. return true;
  435. }
  436. // measure status
  437. public void SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS a_nMsrLoopStatus)
  438. {
  439. m_ThreadStatus.SetStatus( a_nMsrLoopStatus);
  440. }
  441. }
  442. }