SmplMeasure.cpp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482
  1. #pragma once
  2. #include "stdafx.h"
  3. #include <stdlib.h>
  4. #include <crtdbg.h>
  5. #include "SmplMeasure.h"
  6. #include "SmplMsrResultFileMgr.h"
  7. #include "FieldMgr.h"
  8. #include "StageFile.h"
  9. namespace OTSMODEL
  10. {
  11. using namespace OTSDATA;
  12. using namespace std;
  13. CSmplMeasure::CSmplMeasure()
  14. {
  15. Init();
  16. }
  17. CSmplMeasure::CSmplMeasure(CString a_strWorkingFolder, COTSSamplePtr a_pSample)
  18. {
  19. m_pMsrThread = nullptr;
  20. SetSample(a_pSample);
  21. SetWorkingFolder(a_strWorkingFolder);
  22. m_pSmplMsrResultFileMgr = CSmplMsrResultFileMgrPtr(new CSmplMsrResultFileMgr(m_strWorkingFolder));
  23. if (!m_pSmplMsrResultFileMgr->Init(m_pSample))
  24. {// failed to initialize measure result file
  25. LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: initialize measure result file."));
  26. return;
  27. }
  28. }
  29. CSmplMeasure::~CSmplMeasure()
  30. {
  31. }
  32. void CSmplMeasure::SetSample(COTSSamplePtr a_pSample)
  33. {
  34. ASSERT(a_pSample);
  35. if (!a_pSample)
  36. {
  37. LogErrorTrace(__FILE__, __LINE__, _T("SetSample: invalid Sample."));
  38. return;
  39. }
  40. m_pSample = a_pSample;
  41. }
  42. // measure thread
  43. void CSmplMeasure::SetMsrThread(CMsrThread* a_pMsrThread)
  44. {
  45. ASSERT(a_pMsrThread);
  46. if (!a_pMsrThread)
  47. {
  48. LogErrorTrace(__FILE__, __LINE__, _T("SetMsrThread: invalid thread."));
  49. return;
  50. }
  51. m_pMsrThread = a_pMsrThread;
  52. }
  53. void CSmplMeasure::SetWorkingFolder(CString a_strWorkingFolder)
  54. {
  55. // add "\\" at the string end if it is not "\\"
  56. if (a_strWorkingFolder.Right(1) != _T('\\'))
  57. {
  58. a_strWorkingFolder += _T("\\");
  59. }
  60. m_strWorkingFolder = a_strWorkingFolder + m_pSample->GetName() + _T("\\");
  61. }
  62. // measurement
  63. void CSmplMeasure::DoMeasureOneSample()
  64. {
  65. ASSERT(m_pSample);
  66. // let the main thread to know that this sample measurement starts
  67. CMsrSampleStatusPtr pStatus = m_pSample->GetMsrStatus();
  68. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::INPROCESS);
  69. // set current time to current time
  70. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::START);
  71. // let main App know that the sample begin to measure
  72. ST_MSTMsg MsgSmpStart;
  73. memset(&MsgSmpStart, 0, sizeof(ST_MSTMsg));
  74. MsgSmpStart.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS;
  75. MsgSmpStart.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::INPROCESS;
  76. memset(MsgSmpStart.STMSampleStu.cSampleName, 0, sizeof(MsgSmpStart.STMSampleStu.cSampleName));
  77. strcpy(MsgSmpStart.STMSampleStu.cSampleName, m_pSample->GetName());
  78. m_pMsrThread->SendMessageToMeasureApp(MsgSmpStart);
  79. m_pMsrThread->SendLogMessageToMeasureApp(_T(m_pSample->GetName() + " Measurement started!"), PostLogLevel::info);
  80. // get SEM controller to set magnification and working distance
  81. if (!SetSEMDataMrs())
  82. {
  83. //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: fail to set SEM data."));
  84. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  85. // record end time
  86. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  87. return;
  88. }
  89. // get SEM external controll on
  90. if (!SetSEMExteralOn())
  91. {
  92. //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: fail to set SEM external."));
  93. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  94. // record end time
  95. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  96. return;
  97. }
  98. m_pMsrThread->SendLogMessageToMeasureApp(_T(" Set External On!"), PostLogLevel::info);
  99. // set the BSE scan param
  100. if (!SetBSEParam())
  101. {
  102. //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: fail to set BSE param."));
  103. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  104. // record end time
  105. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  106. return;
  107. }
  108. // will be called before quit this method
  109. ON_SCOPE_EXIT([&]()
  110. {// disconnect hardware
  111. SetSEMExteralOff();
  112. ResetScan();
  113. }
  114. );
  115. // record SEM working condition
  116. CSEMDataGnrPtr pSEMDataGnr = m_pMsrThread->GetSEMDataGnr();
  117. ASSERT(pSEMDataGnr);
  118. if (!pSEMDataGnr)
  119. {
  120. // failed to call RecordSEMCondition method
  121. //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to call RecordSEMCondition method."));
  122. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  123. // record end time
  124. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  125. return;
  126. }
  127. m_pSmplMsrResultFileMgr->SetSEMGnr(pSEMDataGnr);
  128. // record SEM data
  129. COTSProjMgrFilePtr pProjMgrFile = m_pMsrThread->GetProjMgrFile();
  130. ASSERT(pProjMgrFile);
  131. if (!pProjMgrFile)
  132. {
  133. // failed to call RecordSEMCondition method
  134. //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to get project file."));
  135. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  136. // record end time
  137. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  138. return;
  139. }
  140. CSEMStageDataPtr pSEMStageData = pProjMgrFile->GetSEMStageData();
  141. ASSERT(pSEMStageData);
  142. if (!pSEMStageData)
  143. {
  144. // failed to call RecordSEMCondition method
  145. //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to get SEM data."));
  146. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  147. // record end time
  148. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  149. return;
  150. }
  151. m_pSmplMsrResultFileMgr->SetSEMStageData(pSEMStageData);
  152. // record stage
  153. CStagePtr pStage = pProjMgrFile->GetStage();
  154. ASSERT(pStage);
  155. if (!pStage)
  156. {// failed to call RecordSEMCondition method
  157. //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to get stage."));
  158. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  159. // record end time
  160. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  161. return;
  162. }
  163. m_pSmplMsrResultFileMgr->SetSEMStage(pStage);
  164. // check if sample measurement completes
  165. COTSImageScanParamPtr pScanParam = m_pSample->GetMsrParams()->GetImageScanParam();
  166. //int nTotalFieldSize = (int)umMeasuredlistFieldCenter.size();
  167. ASSERT(pScanParam);
  168. if (!pScanParam)
  169. {
  170. //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure:invalid Scan param."));
  171. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  172. // record end time
  173. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  174. return;
  175. }
  176. // calculate field centers
  177. std::vector<CPoint> umMeasuredlistFieldCenter;
  178. //umMeasuredlistFieldCenter.clear();
  179. if (!CalculateUnMeasuredFieldsCenters(umMeasuredlistFieldCenter))
  180. {// failed to calculate field centers
  181. //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to calculate field centers."));
  182. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  183. // record end time
  184. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  185. return;
  186. }
  187. //-----save the static measure result file data into xml file and the dynamic data of every field will be saved into sqlite database
  188. CString strPathName = m_pSmplMsrResultFileMgr->GetPathName();
  189. if (!m_pSmplMsrResultFileMgr->Save(strPathName))
  190. {// failed to call measure result file Save method
  191. //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to call measure result file Save method."));
  192. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  193. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  194. return;
  195. }
  196. m_pMsrThread->SendLogMessageToMeasureApp(_T("Created Result File!"), PostLogLevel::info);
  197. //------
  198. int nNewFieldId = 0;
  199. int numOfAllFields = pStatus->GetCompletedFields() + umMeasuredlistFieldCenter.size();//
  200. int completedFields = pStatus->GetCompletedFields();
  201. CString s;
  202. s.Format("%d", umMeasuredlistFieldCenter.size());
  203. m_pMsrThread->SendLogMessageToMeasureApp(_T("Unmeasured fields:") + s, PostLogLevel::info);
  204. for (int i = 0; i < (int)umMeasuredlistFieldCenter.size(); ++i)
  205. {// check and break if stop button is clicked
  206. if (IsAborted())
  207. {// measure stopped
  208. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::STOPPED);
  209. // record end time
  210. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  211. //must wait for the saving data thread finished,or we'll get null pointer exception when we stop the measure process.
  212. while (fieldQueue.size() > 0)
  213. {
  214. Sleep(100);
  215. }
  216. return;
  217. }
  218. if (IsSampleOver(pScanParam, numOfAllFields))
  219. {
  220. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  221. break;
  222. }
  223. // get a field center
  224. CPoint poiFieldCentre = umMeasuredlistFieldCenter[i];
  225. // update thread measure status class, let the main thread know that starts a new field
  226. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  227. ST_MSTMsg MsgFieldStart;
  228. memset(&MsgFieldStart, 0, sizeof(ST_MSTMsg));
  229. MsgFieldStart.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT;
  230. MsgFieldStart.STMSampleRetData.iRetDataType = MSAMPLE_RET::START_MSR_FIELD;
  231. MsgFieldStart.STMSampleRetData.SMsrField.Fieldpos = poiFieldCentre;
  232. m_pMsrThread->SendMessageToMeasureApp(MsgFieldStart);
  233. CString str;
  234. str.Format("%d", i+ completedFields+1);
  235. m_pMsrThread->SendLogMessageToMeasureApp(_T("Current field:") + str, PostLogLevel::warn);
  236. str.Empty();
  237. str.Format("(%d,%d)", poiFieldCentre.x, poiFieldCentre.y);
  238. m_pMsrThread->SendLogMessageToMeasureApp(_T("Begin to move SEM to ") + str, PostLogLevel::info);
  239. // move SEM to the field center
  240. if (!MoveSEMToPoint(poiFieldCentre))
  241. {// failed to move SEM to the position
  242. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  243. // record end time
  244. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  245. continue;
  246. }
  247. m_pMsrThread->SendLogMessageToMeasureApp(_T("Begin to Acquire BSEImage"), PostLogLevel::info);
  248. // take BSE image for the fields
  249. CBSEImgPtr pBSEIamge = AcquireABSEImage();
  250. if (pBSEIamge==nullptr)
  251. {// failed to acquire a BSE image
  252. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  253. // record end time
  254. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  255. m_pMsrThread->SendLogMessageToMeasureApp(_T("Failed to Acquire BSEImage"), PostLogLevel::info);
  256. continue;
  257. }
  258. //BSEData
  259. ST_MSTMsg MsgFieldBSE;
  260. memset(&MsgFieldBSE, 0, sizeof(ST_MSTMsg));
  261. MsgFieldBSE.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT;
  262. MsgFieldBSE.STMSampleRetData.iRetDataType = MSAMPLE_RET::BSE_DATA;
  263. MsgFieldBSE.STMSampleRetData.BSEData.pos.x = poiFieldCentre.x;
  264. MsgFieldBSE.STMSampleRetData.BSEData.pos.y = poiFieldCentre.y;
  265. MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight = pBSEIamge->GetHeight();
  266. MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth = pBSEIamge->GetWidth();
  267. BYTE* pImgData = pBSEIamge->GetImageDataPointer();
  268. MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = pImgData;
  269. m_pMsrThread->SendMessageToMeasureApp(MsgFieldBSE);
  270. m_pMsrThread->SendLogMessageToMeasureApp(_T("Acquire BSE image success! Processing Image....."), PostLogLevel::info);
  271. // get a new field id
  272. nNewFieldId = m_pSmplMsrResultFileMgr->GetIdForANewField(nNewFieldId);
  273. // create a field
  274. COTSFieldDataPtr pNewFieldData = COTSFieldDataPtr(new COTSFieldData());
  275. pNewFieldData->SetId(nNewFieldId);
  276. pNewFieldData->SetPosition(poiFieldCentre);
  277. pNewFieldData->SetFieldFileFolder(m_pSmplMsrResultFileMgr->GetFieldFileSubFolderStr());
  278. // image process
  279. try
  280. {
  281. ImageProcess(pNewFieldData, pBSEIamge);
  282. }
  283. catch (...)
  284. {// catch an exception when call AcquireBSEImage method
  285. m_pMsrThread->SendLogMessageToMeasureApp(_T("Image process failed."), PostLogLevel::warn);
  286. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  287. // record end time
  288. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  289. continue;
  290. }
  291. // is the field data empty
  292. if (!pNewFieldData->IsEmpty())
  293. {
  294. // add the field into the field
  295. m_pSmplMsrResultFileMgr->AddAField(pNewFieldData);
  296. }
  297. // prepare for the next
  298. ++nNewFieldId;
  299. // completed fields
  300. pStatus->SetCompletedFields(pStatus->GetCompletedFields() + 1);
  301. // completed fieldCenter
  302. std::vector<CPoint>& listCpltedCenter = pStatus->GetCompletedFieldsCenter();
  303. listCpltedCenter.push_back(poiFieldCentre);
  304. m_pMsrThread->SendLogMessageToMeasureApp(_T("Send result to the screen!"), PostLogLevel::info);
  305. //Field Data
  306. // record end time
  307. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  308. ST_MSTMsg MsgFieldEnd;
  309. memset(&MsgFieldEnd, 0, sizeof(ST_MSTMsg));
  310. MsgFieldEnd.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT;
  311. MsgFieldEnd.STMSampleRetData.iRetDataType = MSAMPLE_RET::FIELD_DATA;
  312. MsgFieldEnd.STMSampleRetData.SFieldData.iCompleteFieldCount = pStatus->GetCompletedFields();
  313. MsgFieldEnd.STMSampleRetData.SFieldData.iMeasureFieldCount = numOfAllFields;
  314. MsgFieldEnd.STMSampleRetData.SFieldData.iSParticleCount = (int)pNewFieldData->GetParticleList().size();
  315. MsgFieldEnd.STMSampleRetData.SFieldData.Fieldpos.x = poiFieldCentre.x;
  316. MsgFieldEnd.STMSampleRetData.SFieldData.Fieldpos.y = poiFieldCentre.y;
  317. m_pMsrThread->SendMessageToMeasureApp(MsgFieldEnd);
  318. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  319. }
  320. while (fieldQueue.size() > 0)//wait untill all the field data has been saved.
  321. {
  322. Sleep(100);
  323. }
  324. //calculate measure time
  325. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  326. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::SUCCESSED);
  327. // let main thread to know that this sample measurement completes
  328. ST_MSTMsg MsgSmplEnd;
  329. memset(&MsgSmplEnd, 0, sizeof(ST_MSTMsg));
  330. MsgSmplEnd.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS;
  331. MsgSmplEnd.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::SUCCESSED;
  332. memcpy(MsgSmplEnd.STMSampleStu.cSampleName, m_pSample->GetName(), sizeof(m_pSample->GetName()));
  333. m_pMsrThread->SendMessageToMeasureApp(MsgSmplEnd);
  334. return;
  335. }
  336. // hole preview
  337. void CSmplMeasure::DoHolePreviewOneSample(int a_nHoleID)
  338. {// safety check
  339. ASSERT(m_pSample);
  340. // let the main thread to know that this sample measurement starts
  341. CMsrSampleStatusPtr pStatus = m_pSample->GetMsrStatus();
  342. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::INPROCESS);
  343. // set current time to current time
  344. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::START);
  345. // let main App know that the sample begin to measure
  346. ST_MSTMsg MsgSmpStart;
  347. memset(&MsgSmpStart, 0, sizeof(ST_MSTMsg));
  348. MsgSmpStart.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS;
  349. MsgSmpStart.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::INPROCESS;
  350. memset(MsgSmpStart.STMSampleStu.cSampleName, 0, sizeof(MsgSmpStart.STMSampleStu.cSampleName));
  351. strcpy(MsgSmpStart.STMSampleStu.cSampleName, m_pSample->GetName());
  352. // get SEM controller to set magnification and working distance
  353. if (!SetSEMDataMrs())
  354. {
  355. LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: fail to set SEM data."));
  356. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  357. // record end time
  358. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  359. return;
  360. }
  361. // get SEM external controll on
  362. if (!SetSEMExteralOn())
  363. {
  364. LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: fail to set SEM external."));
  365. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  366. // record end time
  367. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  368. return;
  369. }
  370. // set the BSE scan param
  371. if (!SetBSEParam())
  372. {
  373. LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: fail to set BSE param."));
  374. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  375. // record end time
  376. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  377. return;
  378. }
  379. // will be called before quit this method
  380. ON_SCOPE_EXIT([&]()
  381. {// disconnect hardware
  382. SetSEMExteralOff();
  383. ResetScan();
  384. }
  385. );
  386. // check if measurement is aborted
  387. if (IsAborted())
  388. {// measurement aborted
  389. LogTrace(__FILE__, __LINE__, _T("DoHolePreview: measurement aborted before get SEM condition."));
  390. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::STOPPED);
  391. // record end time
  392. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  393. return;
  394. }
  395. // calculate field centers
  396. std::vector<CPoint> listFieldCenter;
  397. listFieldCenter.clear();
  398. if (!CalculateUnMeasuredFieldsCenters(listFieldCenter))
  399. {// failed to calculate field centers
  400. LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: failed to calculate field centers."));
  401. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  402. // record end time
  403. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  404. return;
  405. }
  406. // go through each field
  407. int nNewFieldId = 0;
  408. for (int i = 0; i < (int)listFieldCenter.size(); ++i)
  409. {// check and break if stop button is clicked
  410. if (IsAborted())
  411. {// measure stopped
  412. LogTrace(__FILE__, __LINE__, _T("DoHolePreview: measure thread is stopped."));
  413. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::STOPPED);
  414. // record end time
  415. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  416. return;
  417. }
  418. // check if sample measurement completes
  419. COTSImageScanParamPtr pScanParam = m_pSample->GetMsrParams()->GetImageScanParam();
  420. int nTotalFieldSize = (int)listFieldCenter.size();
  421. ASSERT(pScanParam);
  422. if (!pScanParam)
  423. {
  424. LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview:invalid Scan param."));
  425. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  426. // record end time
  427. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  428. return;
  429. }
  430. if (IsSampleOver(pScanParam, nTotalFieldSize))
  431. {
  432. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  433. break;
  434. }
  435. // get a field center
  436. CPoint poiFieldCentre = listFieldCenter[i];
  437. LogErrorTrace(__FILE__, __LINE__, _T("C++ Position Message 1: field %d begin."), i);
  438. // update thread measure status class, let the main thread know that starts a new field
  439. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  440. ST_MSTMsg MsgFieldStart;
  441. memset(&MsgFieldStart, 0, sizeof(ST_MSTMsg));
  442. MsgFieldStart.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT;
  443. MsgFieldStart.STMSampleRetData.iRetDataType = MSAMPLE_RET::START_MSR_FIELD;
  444. MsgFieldStart.STMSampleRetData.SMsrField.Fieldpos = poiFieldCentre;
  445. LogInfoTrace(__FILE__, __LINE__, _T("Message :DoHolePreview: field %d measure begin. message type is %d"), i, MsgFieldStart.iMsgType);
  446. m_pMsrThread->SendMessageToMeasureApp(MsgFieldStart);
  447. // move SEM to the field center
  448. if (!MoveSEMToPoint(poiFieldCentre))
  449. {// failed to move SEM to the position
  450. LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: failed to move SEM to the field centre point."));
  451. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  452. // record end time
  453. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  454. return;
  455. }
  456. // take BSE image for the fields
  457. CBSEImgPtr pBSEIamge = AcquireABSEImage();
  458. if (!pBSEIamge)
  459. {
  460. // failed to acquire a BSE image
  461. LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: failed to acquire a BSE image."));
  462. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  463. // record end time
  464. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  465. return;
  466. }
  467. //BSEData
  468. ST_MSTMsg MsgFieldBSE;
  469. memset(&MsgFieldBSE, 0, sizeof(ST_MSTMsg));
  470. MsgFieldBSE.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT;
  471. MsgFieldBSE.STMSampleRetData.iRetDataType = MSAMPLE_RET::BSE_DATA;
  472. MsgFieldBSE.STMSampleRetData.BSEData.pos.x = poiFieldCentre.x;
  473. MsgFieldBSE.STMSampleRetData.BSEData.pos.y = poiFieldCentre.y;
  474. MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight = pBSEIamge->GetHeight();
  475. MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth = pBSEIamge->GetWidth();
  476. BYTE* pImgData = pBSEIamge->GetImageDataPointer();
  477. MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = pImgData;
  478. //MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = new BYTE[MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight*MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth];
  479. //memcpy(MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData, pImgData, sizeof(BYTE)*MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight*MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth);
  480. LogErrorTrace(__FILE__, __LINE__, _T("C++ Position Message 4: OTS position x is %d, y is %d is sent in the message."), poiFieldCentre.x, poiFieldCentre.y);
  481. LogInfoTrace(__FILE__, __LINE__, _T("Message : ImageProcess: send BSE data. message type is %d"), MsgFieldBSE.iMsgType);
  482. m_pMsrThread->SendMessageToMeasureApp(MsgFieldBSE);
  483. if (pStatus->GetStatus() != OTS_MSR_SAMPLE_STATUS::INPROCESS)
  484. {
  485. // measurement failed or stopped
  486. LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: measurement failed or stopped."));
  487. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED);
  488. // record end time
  489. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  490. return;
  491. }
  492. //save the result to project file
  493. CHoleBSEImgPtr pHoleBSEImg = CHoleBSEImgPtr(new CHoleBSEImg());
  494. pHoleBSEImg->SetHoleID(a_nHoleID);
  495. pHoleBSEImg->SetPosition(poiFieldCentre);
  496. CRect oImageRect = pBSEIamge->GetImageRect();
  497. long nImageSize = pBSEIamge->GetHeight() * pBSEIamge->GetWidth();
  498. pHoleBSEImg->SetImageRect(oImageRect);
  499. memcpy(pHoleBSEImg->GetImageDataPointer(), pBSEIamge->GetImageDataPointer(), sizeof(BYTE)*nImageSize);
  500. m_listHoleBSEImg.push_back(pHoleBSEImg);
  501. COTSProjMgrFilePtr pProjMgrFile = m_pMsrThread->GetProjMgrFile();
  502. pProjMgrFile->SetHoleBESImgList(m_listHoleBSEImg);
  503. // prepare for the next
  504. ++nNewFieldId;
  505. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  506. ST_MSTMsg MsgFieldEnd;
  507. memset(&MsgFieldEnd, 0, sizeof(ST_MSTMsg));
  508. MsgFieldEnd.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT;
  509. MsgFieldEnd.STMSampleRetData.iRetDataType = MSAMPLE_RET::FIELD_DATA;
  510. MsgFieldEnd.STMSampleRetData.SFieldData.iCompleteFieldCount = (i + 1);
  511. MsgFieldEnd.STMSampleRetData.SFieldData.iMeasureFieldCount = (int)listFieldCenter.size();
  512. MsgFieldEnd.STMSampleRetData.SFieldData.iSParticleCount = 0;
  513. MsgFieldEnd.STMSampleRetData.SFieldData.Fieldpos.x = poiFieldCentre.x;
  514. MsgFieldEnd.STMSampleRetData.SFieldData.Fieldpos.y = poiFieldCentre.y;
  515. LogInfoTrace(__FILE__, __LINE__, _T("Message: DoHolePreview: field %d measure end. message type is %d"), i, MsgFieldEnd.iMsgType);
  516. m_pMsrThread->SendMessageToMeasureApp(MsgFieldEnd);
  517. }
  518. pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED);
  519. //calculate measure time
  520. pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::SUCCESSED);
  521. // let main thread to know that this sample measurement completes
  522. ST_MSTMsg MsgSmplEnd;
  523. memset(&MsgSmplEnd, 0, sizeof(ST_MSTMsg));
  524. MsgSmplEnd.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS;
  525. MsgSmplEnd.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::SUCCESSED;
  526. memcpy(MsgSmplEnd.STMSampleStu.cSampleName, m_pSample->GetName(), sizeof(m_pSample->GetName()));
  527. LogInfoTrace(__FILE__, __LINE__, _T("Message : DoHolePreview: sample %s end. message type is %d"), m_pSample->GetName(), MsgSmplEnd.iMsgType);
  528. m_pMsrThread->SendMessageToMeasureApp(MsgSmplEnd);
  529. }
  530. // hole BSE images list
  531. void CSmplMeasure::SetHoleBESImgList(CHoleBSEImgsList& a_listHoleBSEImg, BOOL a_bClear/* = TRUE*/)
  532. {// clear the hole BSE image list if necessary
  533. if (a_bClear)
  534. {
  535. m_listHoleBSEImg.clear();
  536. }
  537. // go through the input list
  538. for (auto pHoleBSEImg : a_listHoleBSEImg)
  539. {// add the new hole BSE image into HoleBSEImage list
  540. m_listHoleBSEImg.push_back(pHoleBSEImg);
  541. }
  542. }
  543. // samples list
  544. bool CSmplMeasure::SetSysSTDItem(CSTDItemsList& a_listSysSTDItem, BOOL a_bClear/* = TRUE*/)
  545. {// clear samples list if necessary
  546. if (a_bClear)
  547. {
  548. m_listSysSTDItem.clear();
  549. }
  550. // go through the sample list of the source
  551. for (auto pItem : a_listSysSTDItem)
  552. { // create a sample copy
  553. // add the new sample into sample list
  554. m_listSysSTDItem.push_back(pItem);
  555. }
  556. return true;
  557. }
  558. BOOL CSmplMeasure::IsSampleOver(COTSImageScanParamPtr a_pScanParam, int a_nTotalFields)
  559. {
  560. ASSERT(a_pScanParam);
  561. if (!a_pScanParam)
  562. {
  563. LogErrorTrace(__FILE__, __LINE__, _T("IsSampleOver: invalid sample scan param."));
  564. return FALSE;
  565. }
  566. int nStopMode = (int)a_pScanParam->GetStopMode();
  567. int nStopField = a_pScanParam->GetStopParamFields();
  568. // completed fields number
  569. CMsrSampleStatusPtr pMsrSampleStatus = m_pSample->GetMsrStatus();
  570. int nCompeltedField = pMsrSampleStatus->GetCompletedFields();
  571. CMsrResultsPtr pMsrResults = m_pSample->GetMsrResults();
  572. CMsrResultItemsList listMsrResult = pMsrResults->GetResultItems();
  573. int nNumParticle = 0;
  574. for (auto pResult : listMsrResult)
  575. {
  576. if (pResult->GetTypeId() >(int) OTS_PARTCLE_TYPE::NO_ANALYSIS_X_RAY)//summarize the number of the identified particle in this condition
  577. {
  578. nNumParticle += pResult->GetNumber();
  579. }
  580. }
  581. COleDateTimeSpan timeSpan = pMsrSampleStatus->GetUsedTime();
  582. int nDay = timeSpan.GetDays();
  583. int nHour = timeSpan.GetHours();
  584. int nMin = timeSpan.GetMinutes();
  585. int nSec = timeSpan.GetSeconds();
  586. int nUsedTime = nSec + nMin * 60 + nHour * 3600 + nDay * 86400;
  587. int nParticlAim = a_pScanParam->GetStopParamParticles();
  588. int nMeasTimeAim = a_pScanParam->GetStopParamMeasTime();
  589. BOOL bRet = TRUE;
  590. switch(nStopMode)
  591. {
  592. case (int)OTS_MEASURE_STOP_MODE::CoverMode:
  593. // completed fields number
  594. if (nCompeltedField < a_nTotalFields )
  595. {
  596. LogInfoTrace(__FILE__, __LINE__, _T("IsSampleOver: sample measure has not finished."));
  597. bRet = FALSE;
  598. }
  599. break;
  600. case (int)OTS_MEASURE_STOP_MODE::FieldMode:
  601. if (nCompeltedField < nStopField)
  602. {
  603. LogInfoTrace(__FILE__, __LINE__, _T("IsSampleOver: sample measure has not finished."));
  604. bRet = FALSE;
  605. }
  606. break;
  607. case (int)OTS_MEASURE_STOP_MODE::ParticleMode:
  608. if (nNumParticle < nParticlAim)
  609. {
  610. LogInfoTrace(__FILE__, __LINE__, _T("IsSampleOver: sample measure has not finished."));
  611. bRet = FALSE;
  612. }
  613. break;
  614. case (int)OTS_MEASURE_STOP_MODE::TimeMode:
  615. if (nUsedTime < nMeasTimeAim)
  616. {
  617. LogInfoTrace(__FILE__, __LINE__, _T("IsSampleOver: sample measure has not finished."));
  618. bRet = FALSE;
  619. }
  620. break;
  621. default:
  622. break;
  623. }
  624. return bRet;
  625. }
  626. BOOL CSmplMeasure::SetPrjFileSave()
  627. {
  628. ASSERT(m_pMsrThread);
  629. if (!m_pMsrThread)
  630. {
  631. LogErrorTrace(__FILE__, __LINE__, _T("SetPrjFileSave: thread is null."));
  632. return FALSE;
  633. }
  634. COTSProjMgrFilePtr pProjMgr = m_pMsrThread->GetProjMgrFile();
  635. ASSERT(pProjMgr);
  636. if (!pProjMgr)
  637. {
  638. LogErrorTrace(__FILE__, __LINE__, _T("SetPrjFileSave: thread is null."));
  639. return FALSE;
  640. }
  641. pProjMgr->SetModify(TRUE);
  642. return TRUE;
  643. }
  644. BOOL CSmplMeasure::SetSEMDataMrs()
  645. {
  646. ASSERT(m_pSample);
  647. if (!m_pSample)
  648. {
  649. LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMrs: prject sample is empty."));
  650. return FALSE;
  651. }
  652. CSEMDataMsrPtr pSEMDataMsr = m_pSample->GetSEMDataMsr();
  653. ASSERT(pSEMDataMsr);
  654. if (!pSEMDataMsr)
  655. {
  656. LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMrs: failed to get SEM measure data."));
  657. return FALSE;
  658. }
  659. if (*pSEMDataMsr.get() == CSEMDataMsr())
  660. {
  661. LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMrs: SEM measure data is empty."));
  662. return FALSE;
  663. }
  664. double dMag = pSEMDataMsr->GetMagnification();
  665. double dWorkDis = pSEMDataMsr->GetWorkingDistance();
  666. CSemBasePtr pSEMCtrlPtr = GetSEMControl();
  667. ASSERT(pSEMCtrlPtr);
  668. if (!pSEMCtrlPtr)
  669. {
  670. LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMrs: failed to get SEM controller."));
  671. return FALSE;
  672. }
  673. // get SEM controller
  674. if (!pSEMCtrlPtr->IsConnected())
  675. {
  676. if (!pSEMCtrlPtr->Connect())
  677. {
  678. LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMrs: can't connect SEM."));
  679. return FALSE;
  680. }
  681. }
  682. //LogInfoTrace(__FILE__, __LINE__, _T("SetSEMDataMrs:set mag and dis"));
  683. m_pMsrThread->SendLogMessageToMeasureApp("Set mag and dis", PostLogLevel::info);
  684. pSEMCtrlPtr->SetMagnification(dMag);
  685. pSEMCtrlPtr->SetWorkingDistance(dWorkDis);
  686. //LogInfoTrace(__FILE__, __LINE__, _T("SetSEMDataMrs:set mag and dis is over"));
  687. return TRUE;
  688. }
  689. // set SEM external on
  690. BOOL CSmplMeasure::SetSEMExteralOn()
  691. {
  692. CSemBasePtr pSEMCtrlPtr = m_pMsrThread->GetSEMController();
  693. ASSERT(pSEMCtrlPtr);
  694. if (!pSEMCtrlPtr)
  695. {
  696. LogErrorTrace(__FILE__, __LINE__, _T("SetSEMExteralOn: failed to get SEM controller."));
  697. return FALSE;
  698. }
  699. // get SEM controller
  700. if (!pSEMCtrlPtr->IsConnected())
  701. {
  702. if (!pSEMCtrlPtr->Connect())
  703. {
  704. LogErrorTrace(__FILE__, __LINE__, _T("SetSEMExteralOn: can't connect SEM."));
  705. return FALSE;
  706. }
  707. }
  708. pSEMCtrlPtr->SetScanExternal(TRUE);
  709. return TRUE;
  710. }
  711. // set SEM external off
  712. BOOL CSmplMeasure::SetSEMExteralOff()
  713. {
  714. CSemBasePtr pSEMCtrlPtr = m_pMsrThread->GetSEMController();
  715. ASSERT(pSEMCtrlPtr);
  716. if (!pSEMCtrlPtr)
  717. {
  718. LogErrorTrace(__FILE__, __LINE__, _T("SetSEMExteralOff: failed to get SEM controller."));
  719. return FALSE;
  720. }
  721. // get SEM controller
  722. if (!pSEMCtrlPtr->IsConnected())
  723. {
  724. if (!pSEMCtrlPtr->Connect())
  725. {
  726. LogErrorTrace(__FILE__, __LINE__, _T("SetSEMExteralOff: can't connect SEM."));
  727. return FALSE;
  728. }
  729. }
  730. pSEMCtrlPtr->SetScanExternal(FALSE);
  731. m_pMsrThread->SendLogMessageToMeasureApp(_T("Set External Off!"), PostLogLevel::info);
  732. return TRUE;
  733. }
  734. // set BSE param
  735. BOOL CSmplMeasure::SetBSEParam()
  736. {
  737. ASSERT(m_pSample);
  738. if (!m_pSample)
  739. {
  740. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: prject sample is empty."));
  741. return FALSE;
  742. }
  743. // get SEM controller
  744. CSemBasePtr pSEMController = GetSEMControl();
  745. if (!pSEMController)
  746. {
  747. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to get SEM control."));
  748. return FALSE;
  749. }
  750. // get scan controller
  751. COTSScanBasePtr pScanController = GetScanControl();
  752. if (!pScanController)
  753. {
  754. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to get scan control."));
  755. return FALSE;
  756. }
  757. // scan parameters
  758. CMsrParamsPtr pMsrParam = m_pSample->GetMsrParams();
  759. COTSImageScanParamPtr pImgScanParam = pMsrParam->GetImageScanParam();
  760. // get image size
  761. OTS_FIVE_TIES_OPTIONS nImageSizeId = pImgScanParam->GetImagePixelSize();
  762. int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId;
  763. CSize sizePixelImage = RESOLUTION_VALUE[nResulotionId];
  764. // get SEM controller
  765. if (!pSEMController->IsConnected())
  766. {
  767. if (!pSEMController->Connect())
  768. {
  769. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: can't connect SEM."));
  770. return FALSE;
  771. }
  772. }
  773. // get scan field size
  774. double dScanFieldSizeX = sizePixelImage.cx;
  775. double dScanFieldSizeY = sizePixelImage.cy;
  776. if (!pSEMController->GetScanFieldSize(dScanFieldSizeX, dScanFieldSizeY))
  777. {
  778. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to call GetScanFieldSize method."));
  779. return FALSE;
  780. }
  781. // get dwell time
  782. OTS_THREE_TIES_OPTIONS nDwellTime = pImgScanParam->GetScanImageSpeed();
  783. // convert dwell time to bruker dwell time (6, 16, 32)
  784. long nBrukerDwellTimeId = DWELLTIME_BRUKER_ID_THREE_TIE_MIN + (int)nDwellTime;
  785. long nBrukerDwellTime = DWELLTIME_BRUKER_VALUES[nBrukerDwellTimeId];
  786. if (!pScanController->Init())
  787. {
  788. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to get scan control."));
  789. return FALSE;
  790. }
  791. // set dwell time
  792. if (!pScanController->SetDwellTime(nBrukerDwellTime))
  793. {
  794. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to set dwell time (%d) for bruker system."), nBrukerDwellTime);
  795. return FALSE;
  796. }
  797. // set image size
  798. if (!pScanController->SetImageSize(sizePixelImage.cx))
  799. {
  800. // failed to set dwell time
  801. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to set dwell time (%d)."), sizePixelImage.cx);
  802. return FALSE;
  803. }
  804. return TRUE;
  805. }
  806. // reset Scan
  807. BOOL CSmplMeasure::ResetScan()
  808. {
  809. // get scan controller
  810. COTSScanBasePtr pScanController = GetScanControl();
  811. if (!pScanController)
  812. {
  813. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to get scan control."));
  814. return FALSE;
  815. }
  816. // reset Scanner
  817. if (!pScanController->SetAndStartScan())
  818. {
  819. LogErrorTrace(__FILE__, __LINE__, _T("AcquireABSEImage: failed to call SetAndStartScan method."));
  820. return FALSE;
  821. }
  822. m_pMsrThread->SendLogMessageToMeasureApp(_T("Reset Scan!"), PostLogLevel::info);
  823. return true;
  824. }
  825. // initialization
  826. void CSmplMeasure::Init()
  827. {
  828. m_pMsrThread = nullptr;
  829. m_strWorkingFolder = _T("");
  830. }
  831. // check if measurement is aborted
  832. BOOL CSmplMeasure::IsAborted()
  833. {
  834. ASSERT(m_pMsrThread);
  835. return m_pMsrThread->IsMeasureStopped();
  836. }
  837. // hardware control
  838. CSemBasePtr CSmplMeasure::GetSEMControl()
  839. {
  840. // SEM controller
  841. CSemBasePtr pSEMController = nullptr;
  842. // safety check
  843. ASSERT(m_pMsrThread);
  844. if (!m_pMsrThread)
  845. {
  846. LogErrorTrace(__FILE__, __LINE__, _T("GetSEMControl: invalid measure thread pointer."));
  847. return pSEMController;
  848. }
  849. // get SEM controller
  850. pSEMController = m_pMsrThread->GetSEMController();
  851. // return SEM controller
  852. return pSEMController;
  853. }
  854. COTSScanBasePtr CSmplMeasure::GetScanControl()
  855. {
  856. // scan controller
  857. COTSScanBasePtr pScanController = nullptr;
  858. // safety check
  859. ASSERT(m_pMsrThread);
  860. if (!m_pMsrThread)
  861. {
  862. LogErrorTrace(__FILE__, __LINE__, _T("GetScanControl: invalid measure thread pointer."));
  863. return pScanController;
  864. }
  865. // get scan controller
  866. pScanController = m_pMsrThread->GetScanController();
  867. // return scan controller
  868. return pScanController;
  869. }
  870. COTSEDSBasePtr CSmplMeasure::GetEDSControl()
  871. {
  872. // EDS controller
  873. COTSEDSBasePtr pEDSController = nullptr;
  874. // safety check
  875. ASSERT(m_pMsrThread);
  876. if (!m_pMsrThread)
  877. {
  878. LogErrorTrace(__FILE__, __LINE__, _T("GetEDSControl: invalid measure thread pointer."));
  879. return pEDSController;
  880. }
  881. // get EDS controller
  882. pEDSController = m_pMsrThread->GetEDSController();
  883. // return EDS controller
  884. return pEDSController;
  885. }
  886. // get SEM condition (general)
  887. BOOL CSmplMeasure::RecordSEMCondition(CSEMDataGnrPtr a_pSEMDataGnr)
  888. {
  889. // safety check
  890. ASSERT(a_pSEMDataGnr);
  891. if (!a_pSEMDataGnr)
  892. {
  893. LogErrorTrace(__FILE__, __LINE__, _T("RecordSEMCondition: invalid input pointer."));
  894. return FALSE;
  895. }
  896. // get SEM controller
  897. CSemBasePtr pSEMCotroller = GetSEMControl();
  898. ASSERT(pSEMCotroller);
  899. if (!pSEMCotroller)
  900. {
  901. LogErrorTrace(__FILE__, __LINE__, _T("RecordSEMCondition: failed to get SEM controller."));
  902. return FALSE;
  903. }
  904. // get SEM condition (general)
  905. if (!pSEMCotroller->GetSEMDataGnr(a_pSEMDataGnr))
  906. {
  907. LogErrorTrace(__FILE__, __LINE__, _T("RecordSEMCondition: failed to call GetSEMDataGnr method."));
  908. return FALSE;
  909. }
  910. // ok, return TRUE
  911. return TRUE;
  912. }
  913. // calculate field centers
  914. BOOL CSmplMeasure::CalculateUnMeasuredFieldsCenters(std::vector<CPoint>& a_listFieldCenter)
  915. {
  916. // safety check
  917. ASSERT(m_pSample);
  918. // sample measure parameters
  919. CMsrParamsPtr pMsrParam = m_pSample->GetMsrParams();
  920. COTSImageScanParamPtr poImageScanParam = pMsrParam->GetImageScanParam();
  921. CSEMDataMsrPtr poSEMDataMsr = m_pSample->GetSEMDataMsr();
  922. CMsrSampleStatusPtr pMsrStatus = m_pSample->GetMsrStatus();
  923. // measured field centers list
  924. std::vector<CPoint>& listCompletedCenter = pMsrStatus->GetCompletedFieldsCenter();
  925. // field centers list manager
  926. CFieldMgrPtr pFieldMgr = CFieldMgrPtr(new CFieldMgr());
  927. // init field centers list manager
  928. if (!pFieldMgr->Init(m_pSample->GetMsrArea(), poImageScanParam, poSEMDataMsr, listCompletedCenter))
  929. {
  930. LogErrorTrace(__FILE__, __LINE__, _T("CalculateFieldsCenters: failed to init field centres list manager."));
  931. return FALSE;
  932. }
  933. // get field centers list
  934. a_listFieldCenter = pFieldMgr->GetUnmeasuredFieldCentrePoints();// GetFieldCentrePoints();
  935. // ok, return TRUE
  936. return TRUE;
  937. }
  938. // move SEM to the point
  939. BOOL CSmplMeasure::MoveSEMToPoint(CPoint a_poi)
  940. {
  941. /*Sleep(500);*/
  942. // get SEM controller
  943. CSemBasePtr pSEMController = GetSEMControl();
  944. ASSERT(pSEMController);
  945. if (!pSEMController)
  946. {
  947. // failed to get SEM control
  948. LogErrorTrace(__FILE__, __LINE__, _T("MoveSEMToPoint: failed to get SEM control."));
  949. return FALSE;
  950. }
  951. CPoint a_SEMpt;
  952. CStageFilePtr pStageFile = CStageFilePtr(new CStageFile());
  953. CSEMStageDataPtr a_pCSEMStageData = m_pMsrThread->GetProjMgrFile()->GetSEMStageData();
  954. pStageFile->SetStageData(a_pCSEMStageData);
  955. //LogErrorTrace(__FILE__, __LINE__, _T("C++ Position Message 2: OTS position x is %d, y is %d."), a_poi.x, a_poi.y);
  956. if (!pStageFile->ConverOTSToSEMPoint(a_poi, a_SEMpt))
  957. {
  958. return FALSE;
  959. }
  960. //LogErrorTrace(__FILE__, __LINE__, _T("C++ Position Message 3: SEM position x is %d, y is %d."), a_SEMpt.x, a_SEMpt.y);
  961. if (!pSEMController->IsConnected())
  962. {
  963. if (!pSEMController->Connect())
  964. {
  965. LogErrorTrace(__FILE__, __LINE__, _T("MoveSEMToPoint: can't connect SEM."));
  966. return FALSE;
  967. }
  968. }
  969. // move SEM to the position (rotation 0)
  970. if (!pSEMController->MoveSEMToPoint(a_SEMpt, 0))
  971. {
  972. LogErrorTrace(__FILE__, __LINE__, _T("MoveSEMToPoint: failed to call MoveSEMToPoint method."));
  973. return FALSE;
  974. }
  975. //Sleep(500);
  976. return TRUE;
  977. }
  978. // Acquire a BSE image
  979. CBSEImgPtr CSmplMeasure::AcquireABSEImage()
  980. {
  981. // BSE image
  982. CBSEImgPtr pBSEImage = nullptr;
  983. // safety check
  984. ASSERT(m_pSample);
  985. if (!m_pSample)
  986. {
  987. LogErrorTrace(__FILE__, __LINE__, _T("AcquireABSEImage: invalid sample pointer."));
  988. return FALSE;
  989. }
  990. // get scan controller
  991. COTSScanBasePtr pScanController = GetScanControl();
  992. if (!pScanController)
  993. {
  994. LogErrorTrace(__FILE__, __LINE__, _T("AcquireABSEImage: failed to get scan control."));
  995. return pBSEImage;
  996. }
  997. try
  998. {
  999. pBSEImage = pScanController->AcquireBSEImage(0, 0, 2);
  1000. if (pBSEImage==nullptr)
  1001. {
  1002. return nullptr;
  1003. //LogErrorTrace(__FILE__, __LINE__, _T("AcquireABSEImage: the BSE image is invalid."));
  1004. }
  1005. }
  1006. catch (...)
  1007. {
  1008. //LogErrorTrace(__FILE__, __LINE__, _T("AcquireABSEImage: catch an exception when call AcquireBSEImage method."));
  1009. return nullptr;
  1010. }
  1011. return pBSEImage;
  1012. }
  1013. // get x-ray acquire time
  1014. BOOL CSmplMeasure::GetXRayAcquireTime(XRAY_TYPE a_nXrayType, OTS_THREE_TIES_OPTIONS a_nXraySpeed, DWORD& a_nXRayAQTime)
  1015. {
  1016. // safety check
  1017. ASSERT(m_pMsrThread);
  1018. if (!m_pMsrThread)
  1019. {
  1020. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayAcquireTime: invalid thread pointer."));
  1021. return FALSE;
  1022. }
  1023. // get project manager file
  1024. COTSProjMgrFilePtr pOTSProjMgrFile = m_pMsrThread->GetProjMgrFile();
  1025. ASSERT(pOTSProjMgrFile);
  1026. if (!pOTSProjMgrFile)
  1027. {
  1028. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayAcquireTime: failed to get project manager file."));
  1029. return FALSE;
  1030. }
  1031. // x-ray parameters
  1032. COTSXRayParamPtr pXRayParam = pOTSProjMgrFile->GetXRayParam();
  1033. ASSERT(pXRayParam);
  1034. if (!pXRayParam)
  1035. {
  1036. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayAcquireTime: failed to get x-ray parameters."));
  1037. return FALSE;
  1038. }
  1039. a_nXRayAQTime = (DWORD)pXRayParam->GetMidAnalyAQTime();
  1040. // ok, return TRUE
  1041. return TRUE;
  1042. }
  1043. // get x-rays
  1044. BOOL CSmplMeasure::GetXRayByPoints(CPosXraysList& a_listPosXRay, DWORD a_nXRayAQTime, BOOL a_bElementInfo /*= FALSE*/)
  1045. {
  1046. // get EDS controller
  1047. COTSEDSBasePtr pEDSController = GetEDSControl();
  1048. ASSERT(pEDSController);
  1049. if (!pEDSController)
  1050. {
  1051. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByPoints: failed to get EDS controller."));
  1052. return FALSE;
  1053. }
  1054. // init EDS controller
  1055. if (!pEDSController->Init())
  1056. {
  1057. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByPoints: failed to inti EDS (%s)."), pEDSController->GetName());
  1058. return FALSE;
  1059. }
  1060. //// set get quantify info flag, firstly only get x-ray data
  1061. if (!a_bElementInfo)
  1062. {
  1063. pEDSController->SetQuantification(FALSE);
  1064. }
  1065. else
  1066. {
  1067. // get element, because only the first point can get element
  1068. pEDSController->SetQuantification(TRUE);
  1069. }
  1070. int nSize = (int)a_listPosXRay.size();
  1071. if (nSize > 1024)
  1072. {
  1073. m_pMsrThread->SendLogMessageToMeasureApp(_T("Too many point Xray! Divide into multi times!"), PostLogLevel::error);
  1074. int nTimes = nSize / 1024;
  1075. CPosXraysList listPosXRayTemp;
  1076. for (int i = 0; i < nTimes; i++)
  1077. {
  1078. listPosXRayTemp.clear();
  1079. for (int m = 0; m < 1024; m++)
  1080. {
  1081. listPosXRayTemp.push_back(a_listPosXRay[i * 1024 + m]);
  1082. }
  1083. if (!pEDSController->GetXRayByPoints(listPosXRayTemp, a_nXRayAQTime))
  1084. {
  1085. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByPoints: failed to get element."));
  1086. return FALSE;
  1087. }
  1088. }
  1089. int nLast = nSize % 1024;
  1090. if (nLast != 0)
  1091. {
  1092. listPosXRayTemp.clear();
  1093. for (int m = 0; m < nLast; m++)
  1094. {
  1095. listPosXRayTemp.push_back(a_listPosXRay[nTimes * 1024 + m]);
  1096. }
  1097. if (!pEDSController->GetXRayByPoints(listPosXRayTemp, a_nXRayAQTime))
  1098. {
  1099. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByPoints: failed to get element."));
  1100. return FALSE;
  1101. }
  1102. }
  1103. }
  1104. else
  1105. {
  1106. if (!pEDSController->GetXRayByPoints(a_listPosXRay, a_nXRayAQTime))
  1107. {
  1108. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByPoints: failed to get element."));
  1109. return FALSE;
  1110. }
  1111. }
  1112. // ok, return TRUE
  1113. return TRUE;
  1114. }
  1115. BOOL CSmplMeasure::GetXRayByFeatures(COTSParticleList& a_listParticles, CPosXraysList& a_listPosXRay, DWORD a_nXRayAQTime, BOOL a_bElementInfo /*= FALSE*/)
  1116. {
  1117. // get EDS controller
  1118. COTSEDSBasePtr pEDSController = GetEDSControl();
  1119. ASSERT(pEDSController);
  1120. if (!pEDSController)
  1121. {
  1122. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByFeatures: failed to get EDS controller."));
  1123. return FALSE;
  1124. }
  1125. // get out if particles list is empty
  1126. if (a_listParticles.size() == 0)
  1127. {
  1128. return TRUE;
  1129. }
  1130. // init EDS controller
  1131. if (!pEDSController->Init())
  1132. {
  1133. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByFeatures: failed to inti EDS (%s)."), pEDSController->GetName());
  1134. return FALSE;
  1135. }
  1136. // set get quantify info flag
  1137. pEDSController->SetQuantification(a_bElementInfo);
  1138. int nSize = (int)a_listParticles.size();
  1139. if (nSize > 512)
  1140. {
  1141. m_pMsrThread->SendLogMessageToMeasureApp(_T("Too many feature Xray! Divide into multi times!"), PostLogLevel::error);
  1142. }
  1143. int nTimes = nSize / 512;
  1144. int nLast = nSize % 512;
  1145. if (nLast != 0)
  1146. {
  1147. nTimes += 1;
  1148. }
  1149. COTSParticleList listPartTemp;
  1150. CPosXraysList listPosXRayTemp;
  1151. for (int i = 0; i < nTimes; i++)
  1152. {
  1153. listPartTemp.clear();
  1154. listPosXRayTemp.clear();
  1155. for (int m = 0; m < 512; m++)
  1156. {
  1157. if (i * 512 + m < nSize)
  1158. {
  1159. listPartTemp.push_back(a_listParticles[i * 512 + m]);
  1160. listPosXRayTemp.push_back(a_listPosXRay[i * 512 + m]);
  1161. }
  1162. else
  1163. {
  1164. break;
  1165. }
  1166. }
  1167. // get the features list of the particles
  1168. std::vector<std::vector<BrukerSegment>> listBrukerFeatures;//covert these particles into brukerfeatures.
  1169. for (auto pPart : listPartTemp)
  1170. {
  1171. auto pFeature = pPart->GetFeature();
  1172. COTSSegmentsList listSegment = pFeature->GetSegmentsList();
  1173. std::vector<BrukerSegment> listBrukSegment;
  1174. for (auto Segment : listSegment)
  1175. {
  1176. BrukerSegment BrukSeg;
  1177. BrukSeg.XCount = Segment->GetLength();
  1178. BrukSeg.Y = Segment->GetHeight();
  1179. BrukSeg.XStart = Segment->GetStart();
  1180. listBrukSegment.push_back(BrukSeg);
  1181. }
  1182. listBrukerFeatures.push_back(listBrukSegment);
  1183. }
  1184. if (listPosXRayTemp.size() > 0)
  1185. {
  1186. if (!pEDSController->GetXRayByFeatures(listPosXRayTemp, listBrukerFeatures, a_nXRayAQTime))
  1187. {
  1188. LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByFeatures: failed to get xray by features."));
  1189. return FALSE;
  1190. }
  1191. }
  1192. }
  1193. return TRUE;
  1194. }
  1195. // get pixel size
  1196. BOOL CSmplMeasure::GetPixelSize(double& a_dPixelSize)
  1197. {
  1198. // safety check
  1199. ASSERT(m_pSample);
  1200. if (!m_pSample)
  1201. {
  1202. LogErrorTrace(__FILE__, __LINE__, _T("GetPixelSize: invalid sample pointer."));
  1203. return FALSE;
  1204. }
  1205. a_dPixelSize = m_pSample->CalculatePixelSize();
  1206. return TRUE;
  1207. }
  1208. // save a field
  1209. BOOL CSmplMeasure::SaveSampleFile()
  1210. {
  1211. // save the file
  1212. CString strPathName = m_pSmplMsrResultFileMgr->GetPathName();
  1213. if (!m_pSmplMsrResultFileMgr->Save(strPathName))
  1214. {
  1215. // failed to save the file
  1216. LogErrorTrace(__FILE__, __LINE__, _T("SaveAField: failed to save the file."));
  1217. return FALSE;
  1218. }
  1219. // ok, return TRUE
  1220. return TRUE;
  1221. }
  1222. }