MsrThread.cpp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467
  1. // MsrThread.cpp : implementation file
  2. #include "stdafx.h"
  3. #include "resource.h"
  4. #include "MsrThread.h"
  5. #include "FieldMgr.h"
  6. #include "StageFile.h"
  7. #include "COTSHardwareMgr.h"
  8. #include "SmplMeasureInc.h"
  9. #include "STDFileMgr.h"
  10. #include "DlgCheckParamResult.h"
  11. #include "OTSHelper.h"
  12. #include "OTSClassifyEng.h"
  13. #include "boost\scope_exit.hpp"
  14. #include "MultiLang.h"
  15. namespace OTSMODEL {
  16. using namespace OTSController;
  17. CMsrThread::CMsrThread()
  18. {
  19. m_hWnd = NULL;
  20. Init();
  21. }
  22. CMsrThread::CMsrThread(CMsrThread* a_poSource)
  23. {
  24. // input check
  25. ASSERT(a_poSource);
  26. if (!a_poSource)
  27. {
  28. return;
  29. }
  30. // can't copy itself
  31. if (a_poSource == this)
  32. {
  33. return;
  34. }
  35. // copy data over
  36. Duplicate(*a_poSource);
  37. }
  38. CMsrThread::~CMsrThread()
  39. {
  40. }
  41. // init
  42. BOOL CMsrThread::Init(COTSProjMgrFilePtr a_pProjMgrFile, COTSSamplesList a_listMeasuableSamples)
  43. {
  44. // check project file
  45. if (!a_pProjMgrFile)
  46. {
  47. LogErrorTrace(__FILE__, __LINE__, _T("Init: invalide file pointer."));
  48. return FALSE;
  49. }
  50. m_pProjMgrFile = a_pProjMgrFile;
  51. // set measure samples list
  52. // make sure samples in the input samples list are in the working file samples list
  53. // and this sample is switch on
  54. COTSSamplesList& listMeasuableSamples = m_pProjMgrFile->GetSampleList();
  55. m_listMeasurableSamples.clear();
  56. for (auto pSample : a_listMeasuableSamples)
  57. {
  58. /*for (auto pSampleNew : listMeasuableSamples)
  59. {
  60. if(*pSampleNew.get() == *pSample.get())*/
  61. m_listMeasurableSamples.push_back(pSample);
  62. /*}*/
  63. }
  64. // check measure samples list
  65. if (m_listMeasurableSamples.size() == 0)
  66. {
  67. LogErrorTrace(__FILE__, __LINE__, _T("Init: measure samples list is empty."));
  68. return FALSE;
  69. }
  70. // ok, return TRUE
  71. return TRUE;
  72. }
  73. BOOL CMsrThread::Init(COTSProjMgrFilePtr a_pProjMgrFile)
  74. {
  75. // check project file
  76. if (!a_pProjMgrFile)
  77. {
  78. LogErrorTrace(__FILE__, __LINE__, _T("Init: invalide file pointer."));
  79. return FALSE;
  80. }
  81. m_pProjMgrFile = a_pProjMgrFile;
  82. // ok, return TRUE
  83. return TRUE;
  84. }
  85. // measurement
  86. void CMsrThread::DoMeasure()
  87. {
  88. // start measurement, creat thread measure status class, let the main thread know that measurement started
  89. // set measure status to in-process
  90. //record time
  91. static std::map<CString, CSmplMeasurePtr> mapSmplMsr;//use this map to hold all the smplMeasure object
  92. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::START);
  93. COleDateTime timeStart = m_pThreadStatus->GetStartTime();
  94. int iYear = timeStart.GetYear();
  95. int imonth = timeStart.GetMonth();
  96. int iDay = timeStart.GetDay();
  97. int iHour = timeStart.GetHour();
  98. int iMin = timeStart.GetMinute();
  99. int iSec = timeStart.GetSecond();
  100. CString csTime;
  101. csTime.Format("%04d-%02d-%02d %02d:%02d:%02d", iYear, imonth, iDay, iHour, iMin, iSec);
  102. ST_MSTMsg MsgMsrStart;
  103. memset(&MsgMsrStart, 0, sizeof(ST_MSTMsg));
  104. MsgMsrStart.iMsgType = ENUM_MSG_TYPE::MTHREADSTATUS;
  105. MsgMsrStart.STMThreadStu.iMThreadStatus = (int)OTS_MSR_THREAD_STATUS::INPROCESS;
  106. strcpy(MsgMsrStart.STMThreadStu.cMsrStartTime, csTime);
  107. SendMessageToMeasureApp(MsgMsrStart);
  108. //postlog.logLevel = PostLogLevel::info;
  109. SendLogMessageToMeasureApp(_T("Measurement started!"), PostLogLevel::info);
  110. // connect hardware
  111. if (!ConnectHardware())
  112. {
  113. LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to connect hardware."));
  114. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::FAILED);
  115. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  116. ThreadOver();
  117. return;
  118. }
  119. // will be called before quit this method
  120. ON_SCOPE_EXIT([&]()
  121. {
  122. DisconnectHardware();// disconnect hardware
  123. }
  124. );
  125. // set working directory which is the same directory of the setting file
  126. if (!SetWorkingFolderStr())
  127. {
  128. // failed to call SetWorkingFolderStr method
  129. LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to call SetWorkingFolderStr method."));
  130. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::FAILED);
  131. // record end time
  132. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  133. ThreadOver();
  134. return;
  135. }
  136. // get SEM data general
  137. if (!GetSEMDataGnrFromHW())
  138. {
  139. LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to call GetSEMDataGnrFromHW method."));
  140. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::FAILED);
  141. // record end time
  142. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  143. ThreadOver();
  144. return;
  145. }
  146. COTSSamplesList& listMeasuredSamples = m_pThreadStatus->GetCompletedSamples();
  147. // got through measure list
  148. for (auto pSample : m_listMeasurableSamples)
  149. {// check and break if stop button is clicked
  150. if (IsMeasureStopped())
  151. {
  152. // stop button clicked
  153. LogTrace(__FILE__, __LINE__, _T("DoMeasure: stop button is clicked."));
  154. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::STOPPED);
  155. // record end time
  156. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  157. ThreadOver();
  158. return;
  159. }
  160. CSmplMeasurePtr pSmplMeasure;
  161. auto itr = mapSmplMsr.find(pSample->GetName());
  162. if (itr == mapSmplMsr.end())
  163. {// create a sample measure object for the sample
  164. pSmplMeasure=CSmplMeasurePtr(new CSmplMeasureInc(m_strWorkingFolder,pSample));
  165. // set measure thread
  166. pSmplMeasure->SetMsrThread(this);
  167. mapSmplMsr[pSample->GetName ()] = pSmplMeasure;
  168. }
  169. else
  170. {
  171. auto smp1s = m_pProjMgrFile->GetSampleByName(pSample->GetName());
  172. if (smp1s != nullptr)
  173. {
  174. //判断这个project中的sample是否已经测量过
  175. if (pSample->GetMsrStatus()->GetCompletedFields() == 0)
  176. {
  177. pSmplMeasure = CSmplMeasurePtr(new CSmplMeasureInc(m_strWorkingFolder, pSample));
  178. pSmplMeasure->SetMsrThread(this);
  179. mapSmplMsr[pSample->GetName()] = pSmplMeasure;
  180. }
  181. else
  182. {
  183. pSmplMeasure = mapSmplMsr[pSample->GetName()];
  184. pSample->GetMsrStatus()->SetStatus(OTS_MSR_SAMPLE_STATUS::INPROCESS);
  185. SetMsrLoopStatus(OTSDATA::OTS_MSR_THREAD_STATUS::INPROCESS);
  186. }
  187. }
  188. else
  189. {
  190. pSmplMeasure = CSmplMeasurePtr(new CSmplMeasureInc(m_strWorkingFolder, pSample));
  191. pSmplMeasure->SetMsrThread(this);
  192. mapSmplMsr[pSample->GetName()] = pSmplMeasure;
  193. }
  194. }
  195. CSTDItemsList& listSysSTDItem = m_pProjMgrFile->GetSysSTDItem();
  196. pSmplMeasure->SetSysSTDItem(listSysSTDItem, TRUE);
  197. pSmplMeasure->DoMeasureOneSample();
  198. // check if measurement is successful
  199. if (pSample->GetMsrStatus()->GetStatus() == OTS_MSR_SAMPLE_STATUS::STOPPED)
  200. {// record end time
  201. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  202. // measurement stopped
  203. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::STOPPED);
  204. // update thread measure status class, let the main thread know that this sample measurement stopped
  205. ST_MSTMsg MsgSmpStop;
  206. memset(&MsgSmpStop, 0, sizeof(ST_MSTMsg));
  207. MsgSmpStop.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS;
  208. MsgSmpStop.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::STOPPED;
  209. memcpy(MsgSmpStop.STMSampleStu.cSampleName, pSample->GetName(), sizeof(pSample->GetName()));
  210. SendMessageToMeasureApp(MsgSmpStop);
  211. ThreadOver();
  212. return;
  213. }
  214. else if (pSample->GetMsrStatus()->GetStatus() == OTS_MSR_SAMPLE_STATUS::FAILED)
  215. {
  216. // measurement failed
  217. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::FAILED);
  218. // record end time
  219. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  220. // update thread measure status class, let the main thread know that this sample measurement failed
  221. ST_MSTMsg MsgSmpFailed;
  222. memset(&MsgSmpFailed, 0, sizeof(ST_MSTMsg));
  223. MsgSmpFailed.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS;
  224. MsgSmpFailed.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::FAILED;
  225. memcpy(MsgSmpFailed.STMSampleStu.cSampleName, pSample->GetName(), sizeof(pSample->GetName()));
  226. SendMessageToMeasureApp(MsgSmpFailed);
  227. ThreadOver();
  228. continue;// this sample failed then goto next sample.
  229. }
  230. // record end time
  231. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  232. // update thread measure status class, let the main thread know that this sample measurement successes
  233. ST_MSTMsg MsgSmpSuccess;
  234. memset(&MsgSmpSuccess, 0, sizeof(ST_MSTMsg));
  235. MsgSmpSuccess.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS;
  236. MsgSmpSuccess.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::SUCCESSED;
  237. memcpy(MsgSmpSuccess.STMSampleStu.cSampleName, pSample->GetName(), sizeof(pSample->GetName()));
  238. SendMessageToMeasureApp(MsgSmpSuccess);
  239. // continue to the next sample
  240. listMeasuredSamples.push_back(pSample);
  241. }
  242. // measurement completed
  243. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::COMPLETED);
  244. // record end time
  245. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  246. ThreadOver();
  247. }
  248. // hole preview
  249. void CMsrThread::DoHolePreview(int a_nHoleID, CDomainPtr a_pMeasureArea)
  250. {
  251. // start measurement, creat thread measure status class, let the main thread know that measurement started
  252. // set measure status to in-process
  253. //record time
  254. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::START);
  255. COleDateTime timeStart = m_pThreadStatus->GetStartTime();
  256. int iYear = timeStart.GetYear();
  257. int imonth = timeStart.GetMonth();
  258. int iDay = timeStart.GetDay();
  259. int iHour = timeStart.GetHour();
  260. int iMin = timeStart.GetMinute();
  261. int iSec = timeStart.GetSecond();
  262. CString csTime;
  263. csTime.Format("%04d-%02d-%02d %02d:%02d:%02d", iYear, imonth, iDay, iHour, iMin, iSec);
  264. ST_MSTMsg MsgMsrStart;
  265. memset(&MsgMsrStart, 0, sizeof(ST_MSTMsg));
  266. MsgMsrStart.iMsgType = ENUM_MSG_TYPE::MTHREADSTATUS;
  267. MsgMsrStart.STMThreadStu.iMThreadStatus = (int)OTS_MSR_THREAD_STATUS::INPROCESS;
  268. strcpy(MsgMsrStart.STMThreadStu.cMsrStartTime, csTime);
  269. SendMessageToMeasureApp(MsgMsrStart);
  270. // connect hardware
  271. if (!ConnectHardware())
  272. {
  273. // failed to connect hardware
  274. LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: failed to connect hardware."));
  275. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::FAILED);
  276. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  277. ThreadOver();
  278. }
  279. // will be called before quit this method
  280. ON_SCOPE_EXIT([&]()
  281. {
  282. DisconnectHardware();// disconnect hardware
  283. }
  284. );
  285. // Get SEM Message
  286. // create a sample with hole preview param
  287. // current
  288. ASSERT(a_pMeasureArea);
  289. if (!a_pMeasureArea)
  290. {
  291. LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: invalid measure area."));
  292. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::FAILED);
  293. // record end time
  294. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  295. ThreadOver();
  296. return;
  297. }
  298. COTSSamplePtr pSampleHole = CreateHoleSample(a_pMeasureArea);
  299. ASSERT(pSampleHole);
  300. if (!pSampleHole)
  301. {
  302. LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: can't create sample for hole image."));
  303. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::FAILED);
  304. // record end time
  305. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  306. ThreadOver();
  307. return;
  308. }
  309. // create a sample measure object for the sample
  310. CSmplMeasurePtr pSmplMeasure(new CSmplMeasureInc());
  311. // set sample
  312. pSmplMeasure->SetSample(pSampleHole);
  313. // set measure thread
  314. pSmplMeasure->SetMsrThread(this);
  315. // update thread measure status class, let the main thread know that this sample measurement starts
  316. // set working folder string
  317. pSmplMeasure->SetWorkingFolder(m_strWorkingFolder);
  318. // do measure
  319. pSmplMeasure->DoHolePreviewOneSample(a_nHoleID);
  320. // check if measurement is successful
  321. if (pSampleHole->GetMsrStatus()->GetStatus() == OTS_MSR_SAMPLE_STATUS::STOPPED)
  322. {
  323. // record end time
  324. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  325. // measurement stopped
  326. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::STOPPED);
  327. // update thread measure status class, let the main thread know that this sample measurement stopped
  328. ST_MSTMsg MsgSmpStop;
  329. memset(&MsgSmpStop, 0, sizeof(ST_MSTMsg));
  330. MsgSmpStop.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS;
  331. MsgSmpStop.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::STOPPED;
  332. memcpy(MsgSmpStop.STMSampleStu.cSampleName, pSampleHole->GetName(), sizeof(pSampleHole->GetName()));
  333. SendMessageToMeasureApp(MsgSmpStop);
  334. ThreadOver();
  335. return;
  336. }
  337. else if (pSampleHole->GetMsrStatus()->GetStatus() == OTS_MSR_SAMPLE_STATUS::FAILED)
  338. {
  339. // measurement failed
  340. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::FAILED);
  341. // record end time
  342. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  343. // update thread measure status class, let the main thread know that this sample measurement failed
  344. ST_MSTMsg MsgSmpFailed;
  345. memset(&MsgSmpFailed, 0, sizeof(ST_MSTMsg));
  346. MsgSmpFailed.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS;
  347. MsgSmpFailed.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::FAILED;
  348. memcpy(MsgSmpFailed.STMSampleStu.cSampleName, pSampleHole->GetName(), sizeof(pSampleHole->GetName()));
  349. SendMessageToMeasureApp(MsgSmpFailed);
  350. ThreadOver();
  351. return;
  352. }
  353. // record end time
  354. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  355. // update thread measure status class, let the main thread know that this sample measurement successes
  356. ST_MSTMsg MsgSmpSuccess;
  357. memset(&MsgSmpSuccess, 0, sizeof(ST_MSTMsg));
  358. MsgSmpSuccess.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS;
  359. MsgSmpSuccess.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::SUCCESSED;
  360. memcpy(MsgSmpSuccess.STMSampleStu.cSampleName, pSampleHole->GetName(), sizeof(pSampleHole->GetName()));
  361. SendMessageToMeasureApp(MsgSmpSuccess);
  362. // measurement completed
  363. SetMsrLoopStatus(OTS_MSR_THREAD_STATUS::COMPLETED);
  364. // record end time
  365. m_pThreadStatus->ComputeTime(OTS_THREAD_TIME_TYPE::STOPPED);
  366. ThreadOver();
  367. }
  368. // SEM controller
  369. CSemBasePtr CMsrThread::GetSEMController()
  370. {
  371. // create a hardware manager
  372. ASSERT(m_pHardwareMgr);
  373. if (!m_pHardwareMgr)
  374. {
  375. // failed to create a hardware manager
  376. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to create a hardware manager."));
  377. return nullptr;
  378. }
  379. // get SEM, scanner and x-ray controller via hardware manager
  380. CSemBasePtr pSEMCtrlPtr = m_pHardwareMgr->GetSemControllerMgrPtr();
  381. ASSERT(pSEMCtrlPtr);
  382. if (!pSEMCtrlPtr)
  383. {
  384. // failed to get SEM controller
  385. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to get SEM controller."));
  386. return nullptr;
  387. }
  388. return pSEMCtrlPtr;
  389. }
  390. // x-ray controller
  391. COTSEDSBasePtr CMsrThread::GetEDSController()
  392. {
  393. // create a hardware manager
  394. ASSERT(m_pHardwareMgr);
  395. if (!m_pHardwareMgr)
  396. {
  397. // failed to create a hardware manager
  398. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to create a hardware manager."));
  399. return nullptr;
  400. }
  401. // get SEM, scanner and x-ray controller via hardware manager
  402. COTSEDSBasePtr pEDSCtrlPtr = m_pHardwareMgr->GetEDSControllerPtr();
  403. ASSERT(pEDSCtrlPtr);
  404. if (!pEDSCtrlPtr)
  405. {
  406. // failed to get SEM controller
  407. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to get SEM controller."));
  408. return nullptr;
  409. }
  410. return pEDSCtrlPtr;
  411. }
  412. // BSE controller
  413. COTSScanBasePtr CMsrThread::GetScanController()
  414. {
  415. // create a hardware manager
  416. ASSERT(m_pHardwareMgr);
  417. if (!m_pHardwareMgr)
  418. {
  419. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to create a hardware manager."));
  420. return nullptr;
  421. }
  422. // get SEM, scanner and x-ray controller via hardware manager
  423. COTSScanBasePtr pScanCtrlPtr = m_pHardwareMgr->GetScanControllerPtr();
  424. ASSERT(pScanCtrlPtr);
  425. if (!pScanCtrlPtr)
  426. {
  427. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to get SEM controller."));
  428. return nullptr;
  429. }
  430. return pScanCtrlPtr;
  431. }
  432. // measure status
  433. void CMsrThread::SetMsrLoopStatus(OTS_MSR_THREAD_STATUS a_nMsrLoopStatus)
  434. {
  435. if (a_nMsrLoopStatus >= OTS_MSR_THREAD_STATUS::MIN && a_nMsrLoopStatus <= OTS_MSR_THREAD_STATUS::MAX)
  436. {
  437. m_pThreadStatus->SetStatus(a_nMsrLoopStatus);
  438. }
  439. }
  440. //check measure param
  441. //input: COTSProjMgrFilePtr a_pProjMgrFile : work file
  442. // COTSSamplesList& a_listMeasuableSamples : out put -- measure samples list
  443. // BOOL a_bCheckSetting : TRUE check settings
  444. BOOL CMsrThread::CheckMeasureParam(COTSProjMgrFilePtr a_pProjMgrFile, COTSSamplesList& a_listMeasuableSamples, BOOL a_bCheckSetting /*=TRUE*/)
  445. {
  446. // use the dll resource
  447. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  448. // safety check
  449. ASSERT(a_pProjMgrFile);
  450. if (!a_pProjMgrFile)
  451. {
  452. LogErrorTrace(__FILE__, __LINE__, _T("CheckMeasureParam: invalide file pointer"));
  453. return FALSE;
  454. }
  455. // go through the sample list to check setting parameters
  456. int nSwitchSmplNo = 0;
  457. int nCompletedSmplNo = 0;
  458. int nErrorSmplNo = 0;
  459. int nWarningSmplNo = 0;
  460. std::vector<CString> listSamplMessages;
  461. COTSSamplesList listSamples = a_pProjMgrFile->GetSampleList();
  462. COTSSamplesList listMeasurableSamples;
  463. COTSSamplesList listWithWarningMeasurableSamples;
  464. for (auto pSample : listSamples)
  465. {
  466. // is the sample switch on
  467. if (pSample->GetSwitch())
  468. {
  469. ++nSwitchSmplNo;
  470. CString strSmplMessage;
  471. strSmplMessage = pSample->GetName() + _T(":") + _T("\r\n");
  472. // is this a measurement completed sample
  473. if (IsMeasureCompletedSmpl(pSample))
  474. { // measurement completed sample
  475. ++nCompletedSmplNo;
  476. CString str = GetSampleErrorWarnString(SAMPLE_FAULT_WARN_CODE::FINISHED);
  477. strSmplMessage += str;
  478. strSmplMessage += _T("\r\n");
  479. }
  480. else
  481. {
  482. // errors
  483. std::vector<SAMPLE_FAULT_WARN_CODE> a_listErrorCodes;
  484. GetSampleErrorCodes(a_pProjMgrFile,pSample, a_listErrorCodes);
  485. if(!a_listErrorCodes.empty())
  486. {
  487. // has error, this is not a measurable sample
  488. ++nErrorSmplNo;
  489. for (auto& nErrorCode : a_listErrorCodes)
  490. {
  491. CString str = GetSampleErrorWarnString(nErrorCode);
  492. strSmplMessage += str;
  493. strSmplMessage += _T("\r\n");
  494. }
  495. }
  496. else
  497. {
  498. // no error, this is a measurable sample
  499. listMeasurableSamples.push_back(pSample);
  500. }
  501. // warnings
  502. std::vector<SAMPLE_FAULT_WARN_CODE> a_listWarningCodes;
  503. GetSampleWarningCodes(a_pProjMgrFile, pSample, a_listWarningCodes);
  504. if (!a_listWarningCodes.empty())
  505. {
  506. ++nWarningSmplNo;
  507. for (auto& nWarningCode : a_listWarningCodes)
  508. {
  509. CString str = GetSampleErrorWarnString(nWarningCode);
  510. strSmplMessage += str;
  511. strSmplMessage += _T("\r\n");
  512. }
  513. // has no error?
  514. if (a_listErrorCodes.empty())
  515. {
  516. // this is a measurable sample but with setting warnings
  517. listWithWarningMeasurableSamples.push_back(pSample);
  518. }
  519. }
  520. // no error and warning
  521. if (a_listErrorCodes.empty() && a_listWarningCodes.empty())
  522. {
  523. CString str = GetSampleErrorWarnString(SAMPLE_FAULT_WARN_CODE::NO_ERROR_WARNING);
  524. strSmplMessage += str;
  525. strSmplMessage += _T("\r\n");
  526. }
  527. }
  528. // add
  529. listSamplMessages.push_back(strSmplMessage);
  530. }
  531. }
  532. // dlg message string
  533. CString strDlgMessage;
  534. CString str;
  535. CString str1;
  536. str1 = MultiLang::GetInstance().GetCStringByKey(IDS_SAMPLE_CHECK_RESULT + (int)SAMPLE_CHECK_RESULT_TYPE::SWITCH_ON);
  537. str.Format(str1, nSwitchSmplNo);
  538. strDlgMessage += str;
  539. strDlgMessage += _T("\r\n");
  540. // add more string if there switch on sample
  541. if (nSwitchSmplNo > 0)
  542. {
  543. // completed sample number (optional)
  544. if (nCompletedSmplNo > 0)
  545. {
  546. str1 = MultiLang::GetInstance().GetCStringByKey(IDS_SAMPLE_CHECK_RESULT + (int)SAMPLE_CHECK_RESULT_TYPE::FINISHED );
  547. str.Format(str1, nCompletedSmplNo);
  548. strDlgMessage += str;
  549. strDlgMessage += _T("\r\n");
  550. }
  551. // any unmeasured switch on samples?
  552. if(nSwitchSmplNo > nCompletedSmplNo)
  553. {
  554. // with setting error sample number
  555. str1=MultiLang::GetInstance ().GetCStringByKey (IDS_SAMPLE_CHECK_RESULT + (int)SAMPLE_CHECK_RESULT_TYPE::SETTING_ERROR);
  556. str.Format(str1, nErrorSmplNo);
  557. strDlgMessage += str;
  558. strDlgMessage += _T("\r\n");
  559. // with setting warning sample number
  560. str1=MultiLang::GetInstance ().GetCStringByKey (IDS_SAMPLE_CHECK_RESULT + (int)SAMPLE_CHECK_RESULT_TYPE::SETTING_WARNING);
  561. str.Format(str1, nWarningSmplNo);
  562. strDlgMessage += str;
  563. strDlgMessage += _T("\r\n");
  564. }
  565. // measurable sample numbers (has %d there)
  566. str=MultiLang::GetInstance ().GetCStringByKey (IDS_SAMPLE_CHECK_RESULT + (int)SAMPLE_CHECK_RESULT_TYPE::MEASURABLE);
  567. strDlgMessage += str;
  568. strDlgMessage += _T("\r\n");
  569. }
  570. // add an empty line strDlgMessage
  571. strDlgMessage += _T("\r\n");
  572. // add sample messages
  573. for (auto strSmplMessage : listSamplMessages)
  574. {
  575. strDlgMessage += strSmplMessage;
  576. strDlgMessage += _T("\r\n");
  577. }
  578. // do we need to show dialog box?
  579. if(nSwitchSmplNo == 0)
  580. {
  581. LogErrorTrace(__FILE__, __LINE__, _T("CheckMeasureParam: measure button clicked but with no switch on samples."));
  582. return FALSE;
  583. }
  584. // measure button clicked?
  585. if (a_bCheckSetting)
  586. {
  587. // there are measurable samples but no setting warnings samples
  588. if ((int)listMeasurableSamples.size() > 0 && (int)listWithWarningMeasurableSamples.size() == 0)
  589. {
  590. // set output measurable samples list
  591. for (auto pSample : listMeasurableSamples)
  592. {
  593. a_listMeasuableSamples.push_back(pSample);
  594. }
  595. return TRUE;
  596. }
  597. }
  598. //when there is sample setting error, and setting with no error and no warning samples, the dlg will not be show.??
  599. //show the result dlg
  600. CDlgCheckParamResult dlg;
  601. int nTatolMeasuableSmplNo = (int)listMeasurableSamples.size();
  602. int nWithWarningMeasuableSmplNo = (int)listWithWarningMeasurableSamples.size();
  603. // set the dlg parameters
  604. dlg.SetCheckOnlyFlag(a_bCheckSetting);
  605. dlg.SetMessageBase(strDlgMessage);
  606. dlg.SetTatolMeasuableSmplNo(nTatolMeasuableSmplNo);
  607. dlg.SetWithWarningMeasuableSmplNo(nWithWarningMeasuableSmplNo);
  608. //no error not show dlg
  609. if (nTatolMeasuableSmplNo == nSwitchSmplNo - nCompletedSmplNo && listMeasurableSamples.size() != 0)
  610. {
  611. for (auto pSample : listMeasurableSamples)
  612. {
  613. auto itr = std::find(listWithWarningMeasurableSamples.begin(), listWithWarningMeasurableSamples.end(), pSample);
  614. if (itr == listWithWarningMeasurableSamples.end())
  615. {
  616. a_listMeasuableSamples.push_back(pSample);
  617. }
  618. }
  619. m_listMeasurableSamples = a_listMeasuableSamples;//set the measureable samples to the member variable,so we can use it later. gsp.
  620. if (m_listMeasurableSamples.size() > 0)
  621. {
  622. return TRUE;
  623. }
  624. }
  625. //show dlg
  626. if (!(dlg.DoModal() == IDOK))
  627. {
  628. // do something here
  629. return FALSE;
  630. }
  631. else
  632. {
  633. //if warnDo, back the listMeasuableSample
  634. if (dlg.GetWarnDo())
  635. {
  636. for (auto pSample : listMeasurableSamples)
  637. {
  638. a_listMeasuableSamples.push_back(pSample);
  639. }
  640. }
  641. else // back with no warn sample
  642. {
  643. for (auto pSample : listMeasurableSamples)
  644. {
  645. auto itr = std::find(listWithWarningMeasurableSamples.begin(), listWithWarningMeasurableSamples.end(), pSample);
  646. if (itr == listWithWarningMeasurableSamples.end())
  647. {
  648. a_listMeasuableSamples.push_back(pSample);
  649. }
  650. }
  651. }
  652. }
  653. m_listMeasurableSamples = a_listMeasuableSamples;//set the measureable samples to the member variable,so we can use it later. gsp.
  654. return true;
  655. }
  656. // protected
  657. // initialization
  658. void CMsrThread::Init()
  659. {
  660. m_pProjMgrFile = nullptr;
  661. m_listMeasurableSamples.clear();
  662. m_strWorkingFolder = _T("");
  663. m_pThreadStatus = CMsrThreadStatusPtr(new CMsrThreadStatus());
  664. m_pSEMDataGnr = CSEMDataGnrPtr(new CSEMDataGnr());
  665. m_strMAppFormName = _T("");
  666. m_hWnd = NULL;
  667. }
  668. // SEM connection
  669. BOOL CMsrThread::ConnectHardware()
  670. {
  671. // create a hardware manager
  672. m_pHardwareMgr = COTSHardwareMgrPtr(new COTSHardwareMgr());
  673. ASSERT(m_pHardwareMgr);
  674. if (!m_pHardwareMgr)
  675. {
  676. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to create a hardware manager."));
  677. return FALSE;
  678. }
  679. // get SEM, scanner and x-ray controller via hardware manager
  680. CSemBasePtr pSEMCtrlPtr = m_pHardwareMgr->GetSemControllerMgrPtr();
  681. ASSERT(pSEMCtrlPtr);
  682. if (!pSEMCtrlPtr)
  683. {
  684. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to get SEM controller."));
  685. return FALSE;
  686. }
  687. // connect SEM controller
  688. if (!pSEMCtrlPtr->Connect())
  689. {
  690. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to connect SEM (%s)."), pSEMCtrlPtr->GetName());
  691. DisconnectHardware();
  692. return FALSE;
  693. }
  694. // get EDS controller
  695. COTSEDSBasePtr pOTSEDSController = m_pHardwareMgr->GetEDSControllerPtr();
  696. ASSERT(pOTSEDSController);
  697. if (!pOTSEDSController)
  698. {
  699. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to get EDS controller."));
  700. DisconnectHardware();
  701. return FALSE;
  702. }
  703. // init EDS controller
  704. if (!pOTSEDSController->Init())
  705. {
  706. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to inti EDS (%s)."), pOTSEDSController->GetName());
  707. return FALSE;
  708. }
  709. // scanner
  710. COTSScanBasePtr pScanController = m_pHardwareMgr->GetScanControllerPtr();
  711. ASSERT(pScanController);
  712. if (!pScanController)
  713. {
  714. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to get scan controller."));
  715. DisconnectHardware();
  716. return FALSE;
  717. }
  718. // init Scan controller
  719. if (!pScanController->Init())
  720. {
  721. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to inti Scan (%s)."), pScanController->GetName());
  722. DisconnectHardware();
  723. return FALSE;
  724. }
  725. // ok, return TRUE
  726. return TRUE;
  727. }
  728. // release hardware controllers via system manager
  729. void CMsrThread::DisconnectHardware()
  730. {
  731. // create a hardware manager
  732. ASSERT(m_pHardwareMgr);
  733. if (!m_pHardwareMgr)
  734. {
  735. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to create a hardware manager."));
  736. return;
  737. }
  738. // get SEM, scanner and x-ray controller via hardware manager
  739. CSemBasePtr pSEMCtrlPtr = m_pHardwareMgr->GetSemControllerMgrPtr();
  740. ASSERT(pSEMCtrlPtr);
  741. if (pSEMCtrlPtr)
  742. {
  743. pSEMCtrlPtr->Disconnect();
  744. }
  745. // get EDS controller
  746. COTSEDSBasePtr pEDSCtrlPtr = m_pHardwareMgr->GetEDSControllerPtr();
  747. ASSERT(pEDSCtrlPtr);
  748. if (pEDSCtrlPtr)
  749. {
  750. pEDSCtrlPtr->FinishedInstance();
  751. }
  752. COTSScanBasePtr pScanCtrlPtr = m_pHardwareMgr->GetScanControllerPtr();
  753. ASSERT(pScanCtrlPtr);
  754. if (pScanCtrlPtr)
  755. {
  756. pScanCtrlPtr->FinishedInstance();
  757. }
  758. }
  759. // get error codes list of a sample
  760. void CMsrThread::GetSampleErrorCodes(COTSProjMgrFilePtr a_pProjMgrFile, COTSSamplePtr a_pSample, std::vector<SAMPLE_FAULT_WARN_CODE>& a_listErrorCodes)
  761. {
  762. // safety check
  763. ASSERT(a_pSample);
  764. if (!a_pSample)
  765. {
  766. LogErrorTrace(__FILE__, __LINE__, _T("GetSampleErrorCodes: invalid sample pointer."));
  767. return;
  768. }
  769. ASSERT(a_pProjMgrFile);
  770. if (!a_pProjMgrFile)
  771. {
  772. LogErrorTrace(__FILE__, __LINE__, _T("GetSampleErrorCodes: invalid project file pointer."));
  773. return;
  774. }
  775. // check setting error
  776. if (*(a_pSample->GetSEMDataMsr().get()) == CSEMDataMsr())
  777. {
  778. a_listErrorCodes.push_back(SAMPLE_FAULT_WARN_CODE::SEM_DATA_ERROR);
  779. }
  780. // file has not been saved
  781. CString strPathName = a_pProjMgrFile->GetPathName();
  782. // is this a file no saved?
  783. strPathName.Trim();
  784. if (strPathName.CompareNoCase(UNTITLED_FILE_NAME) == 0 || strPathName.IsEmpty())
  785. {
  786. LogErrorTrace(__FILE__, __LINE__, _T("CheckProjFileSave: project has not been saved."));
  787. a_listErrorCodes.push_back(SAMPLE_FAULT_WARN_CODE::FILE_NOT_SAVED);
  788. }
  789. // more error checking...
  790. }
  791. // get warning codes list of a sample
  792. void CMsrThread::GetSampleWarningCodes(COTSProjMgrFilePtr a_pProjMgrFile, COTSSamplePtr a_pSample, std::vector<SAMPLE_FAULT_WARN_CODE>& a_listWarningCodes)
  793. {
  794. // safety check
  795. ASSERT(a_pProjMgrFile);
  796. if (!a_pProjMgrFile)
  797. {
  798. // invalid project file pointer
  799. LogErrorTrace(__FILE__, __LINE__, _T("GetSampleWarningCodes: invalid project file pointer."));
  800. return;
  801. }
  802. ASSERT(a_pSample);
  803. if (!a_pSample)
  804. {
  805. // invalid sample pointer
  806. LogErrorTrace(__FILE__, __LINE__, _T("GetSampleWarningCodes: invalid sample pointer."));
  807. return;
  808. }
  809. // check if the file is valid
  810. if(!a_pProjMgrFile->IsValid())
  811. {
  812. // invalid project file
  813. LogErrorTrace(__FILE__, __LINE__, _T("GetSampleWarningCodes: invalid project file."));
  814. return;
  815. }
  816. // check if the measure domain is cross the sample hole
  817. // get the work stage
  818. CStagePtr pStage = a_pProjMgrFile->GetStage();
  819. //get hole
  820. CString sHoleName = a_pSample->GetSampleHoleName();
  821. //look for the hole Domain
  822. CHolePtr pSampleHole = pStage->GetHoleByName(sHoleName);
  823. if(!pSampleHole)
  824. {
  825. // failed to get the sample hole
  826. LogErrorTrace(__FILE__, __LINE__, _T("GetSampleWarningCodes: failed to get the sample hole."));
  827. return;
  828. }
  829. //// get the measure domain 2019-05-05 注释测量区域是否超越样品
  830. //CDomainPtr pDomain = a_pSample->GetMsrArea();
  831. //if (!pSampleHole->DomainInDomain(*pDomain.get()))
  832. //{
  833. // //sample measure area has part outside the sample hole
  834. // a_listWarningCodes.push_back(SAMPLE_FAULT_WARN_CODE::AREA_OUTSIDE_HOLE);
  835. //}
  836. // resolution
  837. // can only check this if SEM measure data is set
  838. if (!(*(a_pSample->GetSEMDataMsr().get()) == CSEMDataMsr()))
  839. {
  840. // compute pixel size
  841. double dPixleSize = a_pSample->CalculatePixelSize();
  842. // get min size
  843. COTSImageProcessParamPtr pImageProcParam = a_pSample->GetMsrParams()->GetImageProcessParam();
  844. double dMinSize = (double)pImageProcParam->GetIncArea().GetStart();
  845. // if pixel size bigger than 1/2 of the min size, current magnification can't see clear of the object
  846. if (dPixleSize >= dMinSize * 0.5)
  847. {
  848. // resolution low
  849. a_listWarningCodes.push_back(SAMPLE_FAULT_WARN_CODE::RESOLUTION_LOW);
  850. }
  851. }
  852. }
  853. // check sample a measurement completed
  854. BOOL CMsrThread::IsMeasureCompletedSmpl(COTSSamplePtr a_pSample)
  855. {
  856. // safety check
  857. ASSERT(a_pSample);
  858. if (!a_pSample)
  859. {
  860. // invalid sample pointer
  861. LogErrorTrace(__FILE__, __LINE__, _T("IsMeasureCompletedSmpl: invalid sample pointer."));
  862. return FALSE;
  863. }
  864. if(a_pSample->GetMsrStatus()->GetStatus() != OTS_MSR_SAMPLE_STATUS::SUCCESSED)
  865. {
  866. LogTrace(__FILE__, __LINE__, _T("IsMeasureCompletedSmpl: sample has not been measured."));
  867. return FALSE;
  868. }
  869. return TRUE;
  870. }
  871. // error/waring string
  872. CString CMsrThread::GetSampleErrorWarnString(SAMPLE_FAULT_WARN_CODE a_nSampleFaultWarn)
  873. {
  874. // switch to dll resource
  875. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  876. // check input
  877. if (a_nSampleFaultWarn < SAMPLE_FAULT_WARN_CODE::MIN && a_nSampleFaultWarn > SAMPLE_FAULT_WARN_CODE::MAX)
  878. {
  879. LogErrorTrace(__FILE__, __LINE__, _T("GetSampleErrorWarnString: wrong input error/waring string index (%d)."), (int)a_nSampleFaultWarn);
  880. return _T("");
  881. }
  882. // error/waring string
  883. CString strErrorWarn;
  884. strErrorWarn=MultiLang::GetInstance ().GetCStringByKey (IDS_ERROR_WARNING + (int)a_nSampleFaultWarn);
  885. return strErrorWarn;
  886. }
  887. void CMsrThread::GetMeasureAppFormName(const CString& csFormName)
  888. {
  889. m_strMAppFormName = csFormName;
  890. }
  891. BOOL CMsrThread::SendMessageToMeasureApp(ST_MSTMsg Msg)
  892. {
  893. if (NULL == m_hWnd)
  894. {
  895. m_hWnd = ::FindWindow(NULL,m_strMAppFormName);
  896. if (NULL == m_hWnd)
  897. {
  898. LogErrorTrace(__FILE__, __LINE__, _T("(SendMessageToMeasureApp) FindWindow(NULL, m_MAppFormName=%s) failed"), m_strMAppFormName);
  899. return FALSE;
  900. }
  901. }
  902. ::SendMessage(m_hWnd, WM_MEASURE_MSG_ID, 0, (LPARAM)&Msg);
  903. return TRUE;
  904. }
  905. BOOL CMsrThread::SendLogMessageToMeasureApp(CString Msg, PostLogLevel postLogLevel)
  906. {
  907. if (NULL == m_hWnd)
  908. {
  909. m_hWnd = ::FindWindow(NULL, m_strMAppFormName);
  910. if (NULL == m_hWnd)
  911. {
  912. LogErrorTrace(__FILE__, __LINE__, _T("(PostMessageToMeasureApp) FindWindow(NULL, m_MAppFormName=%s) failed"), m_strMAppFormName);
  913. return FALSE;
  914. }
  915. }
  916. memset(&postlog, 0, sizeof(PostLogMessage));
  917. this->postlog.logLevel = postLogLevel;
  918. int l = Msg.GetLength();
  919. if (l > 100)
  920. {
  921. l = 100;
  922. }
  923. for (int i = 0; i < l; i++)
  924. {
  925. this->postlog.logMsg[i] = Msg.GetAt(i);
  926. }
  927. ::SendMessage(m_hWnd, WM_LOG_MSG_ID, 0, (LPARAM)&this->postlog);
  928. return TRUE;
  929. }
  930. void CMsrThread::SetProjMgrFile(COTSProjMgrFilePtr a_pProjMgrFile)
  931. {
  932. ASSERT(a_pProjMgrFile);
  933. if (!a_pProjMgrFile)
  934. {
  935. LogErrorTrace(__FILE__, __LINE__, _T("Set project manager file failed."));
  936. return;
  937. }
  938. m_pProjMgrFile = a_pProjMgrFile;
  939. }
  940. // measurable sample list
  941. void CMsrThread::SetMeasurableSamples(COTSSamplesList& a_listMeasurableSamples)
  942. {
  943. for (auto pSample : a_listMeasurableSamples)
  944. {
  945. m_listMeasurableSamples.push_back(pSample);
  946. }
  947. }
  948. // SEM data general
  949. void CMsrThread::SetSEMDataGnr(CSEMDataGnrPtr a_pSEMDataGnr)
  950. {
  951. ASSERT(a_pSEMDataGnr);
  952. if (!a_pSEMDataGnr)
  953. {
  954. LogErrorTrace(__FILE__, __LINE__, _T("Set sem general data failed."));
  955. return;
  956. }
  957. m_pSEMDataGnr = a_pSEMDataGnr;
  958. }
  959. void CMsrThread::SetMsrThreadStatus(CMsrThreadStatusPtr a_pThreadStatus)
  960. {
  961. ASSERT(a_pThreadStatus);
  962. if (!a_pThreadStatus)
  963. {
  964. LogErrorTrace(__FILE__, __LINE__, _T("Set thread status failed."));
  965. return;
  966. }
  967. m_pThreadStatus = a_pThreadStatus;
  968. }
  969. // working folder string
  970. BOOL CMsrThread::SetWorkingFolderStr()
  971. {
  972. // get project file pathname
  973. CString strSettingFilePathName = m_pProjMgrFile->GetPathName();
  974. strSettingFilePathName.Trim();
  975. if (strSettingFilePathName.IsEmpty())
  976. {
  977. LogErrorTrace(__FILE__, __LINE__, _T("SetWorkingFolderStr: project file pathname is an empty string"));
  978. return FALSE;
  979. }
  980. else if (strSettingFilePathName.CompareNoCase(UNTITLED_FILE_NAME) == 0)
  981. {
  982. LogErrorTrace(__FILE__, __LINE__, _T("SetWorkingFolderStr: project file pathname is an invalid string"));
  983. return FALSE;
  984. }
  985. // working folder string
  986. CString strWorkingFolder = COTSHelper::GetFolderName(strSettingFilePathName);
  987. strWorkingFolder.Trim();
  988. if (strWorkingFolder.IsEmpty())
  989. {
  990. // should be here. working folder string is an empty string
  991. LogErrorTrace(__FILE__, __LINE__, _T("SetWorkingFolderStr: working folder string is an empty string"));
  992. return FALSE;
  993. }
  994. // add "\\" at the string end if it is not "\\"
  995. if (strWorkingFolder.Right(1) != _T('\\'))
  996. {
  997. strWorkingFolder += _T("\\");
  998. }
  999. // set working folder string
  1000. m_strWorkingFolder = strWorkingFolder;
  1001. // ok, return TRUE
  1002. return TRUE;
  1003. }
  1004. COTSSamplePtr CMsrThread::CreateHoleSample(CDomainPtr a_pMsrArea)
  1005. {
  1006. // set measure area
  1007. ASSERT(a_pMsrArea);
  1008. if (!a_pMsrArea)
  1009. {
  1010. LogErrorTrace(__FILE__, __LINE__, _T("CreateHoleSample: invalid measure area pointer."));
  1011. return nullptr;
  1012. }
  1013. COTSSamplePtr pHoleSample = COTSSamplePtr(new COTSSample());
  1014. pHoleSample->SetMsrArea(a_pMsrArea);
  1015. // set SEM measure data
  1016. ASSERT(m_pProjMgrFile);
  1017. if (!m_pProjMgrFile)
  1018. {
  1019. LogErrorTrace(__FILE__, __LINE__, _T("CreateHoleSample: invalid measure working project pointer."));
  1020. return nullptr;
  1021. }
  1022. // get min magnification
  1023. CSEMStageDataPtr pSEMStageData = m_pProjMgrFile->GetSEMStageData();
  1024. double dMinMag = pSEMStageData->GetMinMag();
  1025. // get scan field size 100
  1026. int nScanFieldSize100 = pSEMStageData->GetScanFieldSize100();
  1027. // get working distance
  1028. double dWorkingDistance = 0.0;
  1029. if (!GetSEMWorkingDistanceFromHW(dWorkingDistance))
  1030. {
  1031. LogErrorTrace(__FILE__, __LINE__, _T("CreateHoleSample: Can't get working distance."));
  1032. return nullptr;
  1033. }
  1034. CSEMDataMsrPtr poSEMDataMsr = CSEMDataMsrPtr(new CSEMDataMsr());
  1035. poSEMDataMsr->SetScanFieldSize100(nScanFieldSize100);
  1036. poSEMDataMsr->SetWorkingDistance(dWorkingDistance);
  1037. poSEMDataMsr->SetMagnification(dMinMag);
  1038. pHoleSample->SetSEMDataMsr(poSEMDataMsr);
  1039. // Set image scan param
  1040. COTSImageScanParamPtr poImageScanParam = COTSImageScanParamPtr(new COTSImageScanParam());
  1041. poImageScanParam->SetStopMode(OTS_MEASURE_STOP_MODE::CoverMode);
  1042. poImageScanParam->SetStartImageMode(OTS_GET_IMAGE_MODE::FROM_CENTER);
  1043. poImageScanParam->SetScanImageSpeed(OTS_THREE_TIES_OPTIONS::TIE1);
  1044. poImageScanParam->SetImagePixelSize(OTS_FIVE_TIES_OPTIONS::TIE1);
  1045. CMsrParamsPtr poMsrParams = pHoleSample->GetMsrParams();
  1046. ASSERT(poMsrParams);
  1047. if (!poMsrParams)
  1048. {
  1049. LogErrorTrace(__FILE__, __LINE__, _T("CreateHoleSample: Can't get sample measure param."));
  1050. return nullptr;
  1051. }
  1052. poMsrParams->SetImageScanParam(poImageScanParam);
  1053. pHoleSample->SetMsrParams(poMsrParams);
  1054. return pHoleSample;
  1055. }
  1056. void CMsrThread::Duplicate(const CMsrThread& a_oSource)
  1057. {
  1058. // initialization
  1059. Init();
  1060. // copy data over
  1061. // measure file
  1062. m_pProjMgrFile = a_oSource.m_pProjMgrFile;
  1063. // measure samples list
  1064. for (auto pSample : a_oSource.m_listMeasurableSamples)
  1065. {
  1066. COTSSamplePtr pSampleNew(new COTSSample(pSample.get()));
  1067. m_listMeasurableSamples.push_back(pSampleNew);
  1068. }
  1069. // working folder string
  1070. m_strWorkingFolder = a_oSource.m_strWorkingFolder;
  1071. // measure loop status
  1072. m_pThreadStatus = a_oSource.m_pThreadStatus;
  1073. // SEM data general
  1074. m_pSEMDataGnr = a_oSource.m_pSEMDataGnr;
  1075. //MeasureAppFormName
  1076. m_strMAppFormName = a_oSource.m_strMAppFormName;
  1077. m_hWnd = a_oSource.m_hWnd;
  1078. }
  1079. BOOL CMsrThread::CheckProjFileSave()
  1080. {
  1081. ASSERT(m_pProjMgrFile);
  1082. if (!m_pProjMgrFile)
  1083. {
  1084. LogErrorTrace(__FILE__, __LINE__, _T("CheckProjFileSave: project file is not saved."));
  1085. return FALSE;
  1086. }
  1087. // Save or Save As, if strPathName is not empty, it is exist in the computer, this is a save action
  1088. CString strPathName = m_pProjMgrFile->GetPathName();
  1089. // is this a file no saved?
  1090. strPathName.Trim();
  1091. if (strPathName.CompareNoCase(UNTITLED_FILE_NAME) == 0|| strPathName.IsEmpty())
  1092. {
  1093. LogErrorTrace(__FILE__, __LINE__, _T("CheckProjFileSave: project has not been saved."));
  1094. // return save as result
  1095. return FALSE;
  1096. }
  1097. return TRUE;
  1098. }
  1099. void CMsrThread::ThreadOver()
  1100. {
  1101. // end measurement, let the main thread know that measurement stopped
  1102. COleDateTime timeEnd = m_pThreadStatus->GetEndTime();
  1103. int iYear = timeEnd.GetYear();
  1104. int imonth = timeEnd.GetMonth();
  1105. int iDay = timeEnd.GetDay();
  1106. int iHour = timeEnd.GetHour();
  1107. int iMin = timeEnd.GetMinute();
  1108. int iSec = timeEnd.GetSecond();
  1109. CString csTime;
  1110. csTime.Format("%04d-%02d-%02d %02d:%02d:%02d", iYear, imonth, iDay, iHour, iMin, iSec);
  1111. ST_MSTMsg MsgMsrExit;
  1112. memset(&MsgMsrExit, 0, sizeof(ST_MSTMsg));
  1113. MsgMsrExit.iMsgType = ENUM_MSG_TYPE::MTHREADSTATUS;
  1114. if (IsMeasureStopped())
  1115. {
  1116. MsgMsrExit.STMThreadStu.iMThreadStatus = (int)OTS_MSR_THREAD_STATUS::STOPPED;
  1117. }
  1118. else if (IsMeasureFailed())
  1119. {
  1120. MsgMsrExit.STMThreadStu.iMThreadStatus = (int)OTS_MSR_THREAD_STATUS::FAILED;
  1121. }
  1122. else if (IsMeasureRunning())
  1123. {
  1124. MsgMsrExit.STMThreadStu.iMThreadStatus = (int)OTS_MSR_THREAD_STATUS::INPROCESS;
  1125. }
  1126. else if (IsMeasureCompleted())
  1127. {
  1128. MsgMsrExit.STMThreadStu.iMThreadStatus = (int)OTS_MSR_THREAD_STATUS::COMPLETED;
  1129. }
  1130. strcpy(MsgMsrExit.STMThreadStu.cMsrEndTime, csTime);
  1131. SendMessageToMeasureApp(MsgMsrExit);
  1132. }
  1133. // SEM data general
  1134. BOOL CMsrThread::GetSEMDataGnrFromHW()
  1135. {
  1136. // safety check
  1137. ASSERT(m_pSEMDataGnr);
  1138. if (!m_pSEMDataGnr)
  1139. {
  1140. // should be here. invalid SEM data (general)
  1141. LogErrorTrace(__FILE__, __LINE__, _T("GetSEMDataGnr: invalid SEM data (general)."));
  1142. return FALSE;
  1143. }
  1144. // create a hardware manager
  1145. ASSERT(m_pHardwareMgr);
  1146. if (!m_pHardwareMgr)
  1147. {
  1148. // failed to create a hardware manager
  1149. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to create a hardware manager."));
  1150. return FALSE;
  1151. }
  1152. // get SEM, scanner and x-ray controller via hardware manager
  1153. CSemBasePtr pSEMCtrlPtr = m_pHardwareMgr->GetSemControllerMgrPtr();
  1154. ASSERT(pSEMCtrlPtr);
  1155. if (!pSEMCtrlPtr)
  1156. {
  1157. // failed to create a hardware manager
  1158. LogErrorTrace(__FILE__, __LINE__, _T("ConnectHardware: failed to get SEM controller."));
  1159. return FALSE;
  1160. }
  1161. // get SEM controller
  1162. if (!pSEMCtrlPtr->IsConnected())
  1163. {
  1164. if (!pSEMCtrlPtr->Connect())
  1165. {
  1166. // should be here. can't connect SEM
  1167. LogErrorTrace(__FILE__, __LINE__, _T("GetSEMDataGnr: can't connect SEM."));
  1168. return FALSE;
  1169. }
  1170. }
  1171. // get KV
  1172. double dKV;
  1173. if (!pSEMCtrlPtr->GetHighTension(dKV))
  1174. {
  1175. LogErrorTrace(__FILE__, __LINE__, _T("GetSEMDataGnr: can't get work high voltage value ."));
  1176. return FALSE;
  1177. }
  1178. m_pSEMDataGnr->SetKV(dKV);
  1179. double dBrightness;
  1180. if (!pSEMCtrlPtr->GetBrightness(dBrightness))
  1181. {
  1182. LogErrorTrace(__FILE__, __LINE__, _T("GetSEMDataGnr: can't get brightness ."));
  1183. return FALSE;
  1184. }
  1185. m_pSEMDataGnr->SetBrightness(dBrightness);
  1186. double dContrast;
  1187. if (!pSEMCtrlPtr->GetContrast(dContrast))
  1188. {
  1189. LogErrorTrace(__FILE__, __LINE__, _T("GetSEMDataGnr: can't get dContrast."));
  1190. return FALSE;
  1191. }
  1192. m_pSEMDataGnr->SetContrast(dContrast);
  1193. return TRUE;
  1194. }
  1195. BOOL CMsrThread::GetSEMWorkingDistanceFromHW(double& a_dWorkingDistance)
  1196. {
  1197. // create a hardware manager
  1198. ASSERT(m_pHardwareMgr);
  1199. if (!m_pHardwareMgr)
  1200. {
  1201. // failed to create a hardware manager
  1202. LogErrorTrace(__FILE__, __LINE__, _T("GetSEMWorkingDistanceFromHW: failed to create a hardware manager."));
  1203. return FALSE;
  1204. }
  1205. // get SEM, scanner and x-ray controller via hardware manager
  1206. CSemBasePtr pSEMCtrlPtr = m_pHardwareMgr->GetSemControllerMgrPtr();
  1207. ASSERT(pSEMCtrlPtr);
  1208. if (!pSEMCtrlPtr)
  1209. {
  1210. LogErrorTrace(__FILE__, __LINE__, _T("GetSEMWorkingDistanceFromHW: failed to get SEM controller."));
  1211. return FALSE;
  1212. }
  1213. // get SEM controller
  1214. if (!pSEMCtrlPtr->IsConnected())
  1215. {
  1216. if (!pSEMCtrlPtr->Connect())
  1217. {
  1218. LogErrorTrace(__FILE__, __LINE__, _T("GetSEMWorkingDistanceFromHW: can't connect SEM."));
  1219. return FALSE;
  1220. }
  1221. }
  1222. double dWorkDis = 0;
  1223. if (!pSEMCtrlPtr->GetWorkingDistance(a_dWorkingDistance))
  1224. {
  1225. LogErrorTrace(__FILE__, __LINE__, _T("GetSEMWorkingDistanceFromHW: can't get working distance."));
  1226. return FALSE;
  1227. }
  1228. return TRUE;
  1229. }
  1230. BOOL CMsrThread::GetClassifyParticleId(CPartSTDDataPtr a_pPartSTDData, int steelTech, CElementChemistriesList& a_listElementChemistries, int& a_nIncId)
  1231. {
  1232. if (!COTSClassifyEng::ClassifyXray(a_pPartSTDData, (STEEL_TECHNOLOGY)steelTech, a_listElementChemistries, a_nIncId))
  1233. {// invalid x-ray pointer.
  1234. LogErrorTrace(__FILE__, __LINE__, _T("ClassifyParticle: can't identify the particle as any inclusion."));
  1235. return FALSE;
  1236. }
  1237. if (a_nIncId < 8)
  1238. {
  1239. a_nIncId = (int)OTS_PARTCLE_TYPE::NOT_IDENTIFIED;
  1240. }
  1241. // ok, return TRUE
  1242. return TRUE;
  1243. }
  1244. }