#include "stdafx.h" #include "SmplMeasureInc.h" #include "OTSFieldMgr.h" #include "STDXMLFileMnr.h" #include "OTSClassifyEng.h" #include #include "IClassifyEngine.h" namespace OTSMODEL { using namespace OTSClassifyEngine; CSmplMeasureInc::CSmplMeasureInc() { } CSmplMeasureInc::CSmplMeasureInc(CString a_strWorkingFolder,COTSSamplePtr a_pSample):CSmplMeasure(a_strWorkingFolder, a_pSample) { } CSmplMeasureInc::~CSmplMeasureInc() { bSaveThreadWorking = false; } // class methods // public // field image process void CSmplMeasureInc::ImageProcess(COTSFieldDataPtr a_pFieldData, CBSEImgPtr a_pBSEImg) { // measure status CMsrSampleStatusPtr pStatus = m_pSample->GetMsrStatus(); // EDS controller COTSEDSBasePtr pEDSController = GetEDSControl(); ASSERT(pEDSController); if (!pEDSController) {// failed to get EDS controller pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); return; } // create a field data manager COTSFieldMgrPtr pFieldMgr = COTSFieldMgrPtr(new COTSFieldMgr()); pFieldMgr->SetMsrStatus(pStatus); if (!pFieldMgr->Init(a_pFieldData, a_pBSEImg)) {// failed to initialize the field data manager pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); return; } // get image process parameter CMsrParamsPtr pMsrParam = m_pSample->GetMsrParams(); COTSImageProcessParamPtr pImgProcessParam = pMsrParam->GetImageProcessParam(); /* remove BES image background */ if (!pFieldMgr->RemoveBSEImageBG(pImgProcessParam)) {// failed to call RemoveBSEImageBG method pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); return; } m_pMsrThread->SendLogMessageToMeasureApp(_T(" Image Process Success!"), PostLogLevel::info); // check if this is an empty image if (pFieldMgr->NoParticle()) {// empty fields m_pMsrThread->SendLogMessageToMeasureApp(_T(" Image have no particles!"), PostLogLevel::warn); return; } // remove over sized particles, too small particles and get a analysis particles list // get pixel size double dPixelSize; if (!GetPixelSize(dPixelSize)) {// failed to call GetPixelSize method pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); return; } //Get measured area DWORD nMeasuredArea = 0; // this area should be the field area nMeasuredArea = (DWORD)(a_pBSEImg->GetHeight() * a_pBSEImg->GetWidth() * dPixelSize * dPixelSize + 0.5); // get x-ray parameters COTSXRayParamPtr pXRayParam = pMsrParam->GetXRayParam(); // calculate search x-ray acquire time DWORD nXRayAQTime; COTSParticleList listAnalysisParticles; CPosXraysList listAnalysisXRay; ////============================================= //// particle x-ray analysis ////============================================= if (!pFieldMgr->ProcessParticles(pImgProcessParam, dPixelSize, listAnalysisParticles)) {// failed to call ProcessParticles method pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); StartSaveFileThread(pFieldMgr); return; } // make sure if the particles list is not empty if (listAnalysisParticles.empty()) { StartSaveFileThread(pFieldMgr); m_pMsrThread->SendLogMessageToMeasureApp(_T("There is no particles to be analyzed!"), PostLogLevel::warn); return; } if (!pFieldMgr->CreateXrayList(listAnalysisParticles, listAnalysisXRay)) {// failed to call CreateXrayList method pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); StartSaveFileThread(pFieldMgr); return; } if (listAnalysisParticles.size() != listAnalysisXRay.size()) { pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); StartSaveFileThread(pFieldMgr); return; } // let the main thread to know that particle analysis x-ray is done and number of x-ray points nXRayAQTime = pXRayParam->GetMidAnalyAQTime(); if (pXRayParam->GetScanMode() == OTS_X_RAY_SCAN_MODE::PointMode) {// get x-ray list (analysis) by points nXRayAQTime = pXRayParam->GetMidAnalyAQTime(); CString xraymsg; xraymsg.Format("Begin point mode xray collection,AQTime:%d XrayNum:%d", nXRayAQTime, listAnalysisParticles.size()); m_pMsrThread->SendLogMessageToMeasureApp(xraymsg, PostLogLevel::info); if (!GetXRayByPoints(listAnalysisXRay, nXRayAQTime, TRUE)) {// failed to call GetXRayByPoints method pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); StartSaveFileThread(pFieldMgr); m_pMsrThread->SendLogMessageToMeasureApp("Xray collection failed!", PostLogLevel::info); return; } } else {// get x-ray list (analysis) by particle features nXRayAQTime = pXRayParam->GetMidAnalyAQTime(); CString xraymsg; xraymsg.Format("Begin feature mode xray collection,AQTime:%d XrayNum:%d", nXRayAQTime, listAnalysisParticles.size()); m_pMsrThread->SendLogMessageToMeasureApp(xraymsg, PostLogLevel::info); if (!GetXRayByFeatures(listAnalysisParticles, listAnalysisXRay, nXRayAQTime, TRUE)) { pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); StartSaveFileThread(pFieldMgr); m_pMsrThread->SendLogMessageToMeasureApp("Xray collection failed!", PostLogLevel::info); return; } } m_pMsrThread->SendLogMessageToMeasureApp(_T(" Xray collection finished!"), PostLogLevel::info); // let the main thread to know that is about to do particle analysis x-ray and number of x-ray points // save analysis x-ray into field data pFieldMgr->SetAnalysisPosXayList(listAnalysisXRay); CString xraymsg; xraymsg.Format("Begin to classify particles! num:%d", listAnalysisParticles.size()); m_pMsrThread->SendLogMessageToMeasureApp(xraymsg , PostLogLevel::info); // classify Particles if(!ClassifyParticles(listAnalysisParticles, listAnalysisXRay)) { pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); StartSaveFileThread(pFieldMgr); return; } // save field files m_pMsrThread->SendLogMessageToMeasureApp(_T("Begin to save the result to database!"), PostLogLevel::info); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::SUCCESSED); StartSaveFileThread(pFieldMgr); m_pMsrThread->SendLogMessageToMeasureApp(_T("Begin to do the statistics and display on screen!"), PostLogLevel::info); // on-line classification (field) if (!pFieldMgr->OnLineClassification()) { pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); return; } // Cumulate field data info into sample if (!CumulateFieldData(pFieldMgr->GetMsrResult(), nMeasuredArea)) {// failed to call SaveFieldFile method pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); return; } // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } void CSmplMeasureInc::SaveFieldMgrData() { while( bSaveThreadWorking) { while (fieldQueue.size() > 0) { COTSFieldMgrPtr f = fieldQueue.front(); double pixelSize = 0; this->GetPixelSize(pixelSize); try { f->CalIncAParticleImageProp(pixelSize); f->SaveFieldFiles(); } catch (const std::exception&) { LogErrorTrace(__FILE__, __LINE__, _T("ImageProcess: calcu the particle image property or save to db failed.")); } //save to disk first ,then pop . if the size is 0,then we know all the saving work is done. fieldQueue.pop(); } if (fieldQueue.size() == 0) { bSaveThreadWorking = false;//must set this flag,so the main thread can know this thread has exited. return; } } return; } void CSmplMeasureInc::StartSaveFileThread(COTSFieldMgrPtr a_pFieldMgr) { ASSERT(a_pFieldMgr); if (!a_pFieldMgr) { // invalid sample pointer. LogErrorTrace(__FILE__, __LINE__, _T("StartSaveFileThread: empty field pointer.")); return; } fieldQueue.push(a_pFieldMgr); if (fieldQueue.size() > 0)//if there's data in the queue and the previous thread has finished then start a new thread. { if (bSaveThreadWorking == false) { bSaveThreadWorking = true; m_thread_ptr = shared_ptr(new thread(&CSmplMeasureInc::SaveFieldMgrData, this)); m_thread_ptr->detach(); } } } // Cumulate field data info BOOL CSmplMeasureInc::CumulateFieldData(CMsrResultsPtr a_pFieldMsrResults, DWORD a_nMeasuredArea) { // safety check ASSERT(m_pSample); if (!m_pSample) { // invalid sample pointer. LogErrorTrace(__FILE__, __LINE__, _T("CumulateFieldData: invalid sample pointer.")); return FALSE; } ASSERT(a_pFieldMsrResults); if (!a_pFieldMsrResults) { // invalid field measure result pointer. LogErrorTrace(__FILE__, __LINE__, _T("CumulateFieldData: invalid field measure result pointer.")); return FALSE; } // get measure result items CMsrResultItemsList& listResultItems = a_pFieldMsrResults->GetResultItems(); // get measure result items of the sample CMsrResultsPtr pMsrResults = m_pSample->GetMsrResults(); // cumulate field data info pMsrResults->CumulateMeasureResults(listResultItems); pMsrResults->CumulateMeasuredArea(a_nMeasuredArea); // cumulate ratio double dRatio = 10000 * pMsrResults->GetTotalParticleArea(); dRatio = dRatio / pMsrResults->GetMeasuredArea(); pMsrResults->SetRadio(dRatio); // ok, return TRUE return TRUE; } // protected // classify particles BOOL CSmplMeasureInc::ClassifyParticles(COTSParticleList& a_listAnalysisParticles, CPosXraysList& a_listAnalysisXRay) { // make sure the two lists are same size int nSize = (int)a_listAnalysisParticles.size(); if ( nSize != (int)a_listAnalysisXRay.size()) { // particles list size is different with x-ray size LogErrorTrace(__FILE__, __LINE__, _T("ClassifyParticles: particles list size is different with x-ray size.")); return FALSE; } // go through all analysis particles for (int i = 0; i < nSize; ++i) { COTSParticlePtr pParticle = a_listAnalysisParticles[i]; CPosXrayPtr pXray = a_listAnalysisXRay[i]; if (!ClassifyParticle(pParticle, pXray)) { // failed to call ClassifyParticle method LogErrorTrace(__FILE__, __LINE__, _T("ClassifyParticles: failed to call ClassifyParticle method.")); return FALSE; } } // ok, return TRUE return TRUE; } BOOL CSmplMeasureInc::ClassifyParticle(COTSParticlePtr a_pParticle, CPosXrayPtr a_pXRay) { //set the particle type to NOT_IDENTIFIED int nInclusionID = (int)OTS_PARTCLE_TYPE::NOT_IDENTIFIED; // safety check ASSERT(m_pSample); if (!m_pSample) { // invalid sample pointer. LogErrorTrace(__FILE__, __LINE__, _T("ClassifyParticle: invalid sample pointer.")); return FALSE; } ASSERT(a_pParticle); if (!a_pParticle) { // invalid particle pointer. LogErrorTrace(__FILE__, __LINE__, _T("ClassifyParticle: invalid particle pointer.")); return FALSE; } ASSERT(a_pXRay); if (!a_pXRay) { // invalid x-ray pointer. LogErrorTrace(__FILE__, __LINE__, _T("ClassifyParticle: invalid x-ray pointer.")); return FALSE; } //// 1.get elementChemistries CElementChemistriesList listElementChemistriesOld = a_pXRay->GetElementQuantifyData(); //get the parameter MsrParam object CMsrParamsPtr pMsrParam = m_pSample->GetMsrParams(); //get the steel technology parameter STEEL_TECHNOLOGY steelTech = pMsrParam->GetSteelTechnology(); //get standard database item which will be used when classify. CPartSTDDataPtr pPartSTDData = pMsrParam->GetPartSTDData(); int listSize = pPartSTDData->GetSTDItemsList().size(); if(!COTSClassifyEng::ClassifyXray(pPartSTDData,steelTech, listElementChemistriesOld, nInclusionID)) { // invalid x-ray pointer. LogErrorTrace(__FILE__, __LINE__, _T("ClassifyParticle: can't identify the particle as any inclusion.")); return FALSE; } if (nInclusionID<7) { nInclusionID = (int)OTS_PARTCLE_TYPE::NOT_IDENTIFIED; } if (nInclusionID == (int)OTS_PARTCLE_TYPE::NOT_IDENTIFIED) { //OTSClassifyEngine::CLEEnginePtr en = GetParticleEngine(); //en->Classify(a_pParticle, a_pXRay);//if there is a item match the particle then the item's typeId, color and name will be put into the particle. } else { auto stdItem = pPartSTDData->GetSTDItemById(nInclusionID); if (stdItem != nullptr) { a_pParticle->SetType(nInclusionID); a_pParticle->TypeName(stdItem->GetName().GetBuffer()); a_pParticle->TypeColor(stdItem->GetColor().GetBuffer()); } } return TRUE; } // check sample STD to make sure it will not be an empty one BOOL CSmplMeasureInc::CheckSmplSTD() { // safety check ASSERT(m_pSample); if (!m_pSample) { // invalid sample handle LogErrorTrace(__FILE__, __LINE__, _T("CheckSmplSTD: invalid sample handle.")); return FALSE; } // get sample measure parameter CMsrParamsPtr pMsrParam = m_pSample->GetMsrParams(); // get sample STD CPartSTDDataPtr pPartSTDData = pMsrParam->GetPartSTDData(); // check if sample STD is empty if (*pPartSTDData.get() == CPartSTDData()) { // sample STD is empty, replace it with system STD pPartSTDData->SetSTDItemsList(m_listSysSTDItem, TRUE); } // ok, return true return TRUE; } }