#pragma once #include "stdafx.h" #include "ExpressionClassifyEngine.h" #include "ExpressionParseEngine/LogicExp.h" #include "XMLSerialization.h" #include #include #include "ExpressionParseEngine/OTSSTDLibFileMgr.h" #include "COTSUtilityDllFunExport.h" namespace OTSClassifyEngine { using namespace expInterpreter; bool ExpressionClassifyEngine::Init() { CSTDLibFileMgrPtr pLibFileMgr = CSTDLibFileMgrPtr(new CSTDLibFileMgr(m_StrName)); m_std = ParticleSTDPtr(new ParticleSTD()); if (!pLibFileMgr->LoadPartSTD(m_std)) { return FALSE; } pLibFileMgr->LoadMaxEDSRulesData(m_std); if (!pLibFileMgr->LoadZeroElementRulesData(m_std)) { //return false; } string constantStr = pLibFileMgr->LoadConstantsData(); std::map m_mapConstants; m_mapConstants.clear(); std::vector strs; xmls::SplitString(constantStr, strs, ","); for (std::string s : strs) { std::vector oneExp; xmls::SplitString(s, oneExp, "="); m_mapConstants[oneExp[0]] = std::atof(oneExp[1].c_str()); } m_std->setConstantsMap(m_mapConstants); return true; } bool ExpressionClassifyEngine::ClassifyExpression(COTSParticlePtr particle, CPosXrayPtr xray) { if (particle != nullptr && xray != nullptr)//process the particle with the xray data { auto& originalPartEles = xray->GetElementQuantifyData();//find all the elements containing in the particle xray. //zero element process,if satisfied the condition than set the particular element percentage to 0.and make it 100% of all the other element percentage. auto partEles = ZeroElementProcess(particle, xray);// std::map mapChemistrys; for (auto ch : partEles) { mapChemistrys[ch->GetName().GetBuffer()] = ch; } PartSTDRuleItemList ruleItems = m_std->GetSTDRuleItems(); std::vector matchedItems; for (auto itm : ruleItems) { //if the element quantity is not match the std item's keyelement num than they are unmatching. if (partEles.size() < itm->GetKeyElementList().size()) { continue; } auto& mapStdEles = itm->GetMapElements(); bool bMatch = true; // if the particle does not contain all the key elements of the item than they are unmatching. for (auto che : mapStdEles) { auto chemical = mapChemistrys.find(che.second->GetName().GetBuffer()); if (chemical == mapChemistrys.end()) { bMatch = false; break; } } if (!bMatch) continue; std::string exp = itm->GetExpressionStr(); ProcessAllPropertiesWithParticleData(exp, mapChemistrys, itm, particle); //calculate the expression which has been processed. bool rst = CalcuExp(exp); if (rst) { matchedItems.push_back(itm); } else { continue; } } if (matchedItems.size() > 0) { auto matchedItem = matchedItems[0]; for (auto itm : matchedItems) { if (itm->GetExpressionStr().size() > matchedItem->GetExpressionStr().size()) { matchedItem = itm; } } particle->SetType(OTS_PARTICLE_TYPE::IDENTIFIED); particle->SetClassifyId(matchedItem->GetID()); particle->SetColor(matchedItem->GetColor()); particle->SetClassifyName(matchedItem->GetName()); particle->SetHardness(matchedItem->GetHardness()); particle->SetDensity(matchedItem->GetDensity()); particle->SetConductivity(matchedItem->GetElectrical_conductivity()); particle->SetGroupId(matchedItem->GetGrpID()); particle->SetGroupColor(matchedItem->GetGrpColor()); particle->SetGroupName(matchedItem->GetGrpName()); if (matchedItem->GetIsElementAnalysis() == false) { matchedItem->AddXraySpectrum(particle->GetXrayInfo()); } } else { particle->SetType(OTS_PARTICLE_TYPE::NOT_IDENTIFIED); particle->SetClassifyName("Not Identified"); particle->SetColor("#000000"); particle->SetGroupId((int)OTS_PARTICLE_TYPE::NOT_IDENTIFIED); particle->SetGroupName("Not Identified"); particle->SetGroupColor("#000000"); } return true; } else if(particle != nullptr && xray == nullptr)//process particle without xray data { PartSTDRuleItemList stdItems = m_std->GetSTDRuleItems(); for (auto itm : stdItems) { std::string exp = itm->GetExpressionStr(); //if the rule demand any element infomation then they won't match. if (itm->GetKeyElementList().size() > 0 || itm->GetSubElementList().size() > 0) { continue; } ProcessImgPropertiesWithParticleData(exp, itm, particle); //calculate the expression which has been processed. bool rst = CalcuExp(exp); if (rst) { //int id = itm->GetID(); particle->SetType(OTS_PARTICLE_TYPE::IDENTIFIED); particle->SetClassifyId(itm->GetID()); particle->SetColor(itm->GetColor()); particle->SetClassifyName(itm->GetName()); particle->SetHardness(itm->GetHardness()); particle->SetDensity(itm->GetDensity()); particle->SetConductivity(itm->GetElectrical_conductivity()); particle->SetGroupId(itm->GetGrpID()); particle->SetGroupColor(itm->GetGrpColor()); particle->SetGroupName(itm->GetGrpName()); return true; } else { continue; } } particle->SetType(OTS_PARTICLE_TYPE::NOT_IDENTIFIED); particle->SetClassifyName("Not Identified"); particle->SetColor("#000000"); particle->SetGroupId((int)OTS_PARTICLE_TYPE::NOT_IDENTIFIED); particle->SetGroupColor("#000000"); particle->SetGroupName("Not Identified"); return true; } } bool ExpressionClassifyEngine::IfNeedMaxEDS(COTSParticlePtr particle, CPosXrayPtr xray, double& MaxEDSTime) { if (particle == nullptr || xray == nullptr) return false; MaxEDSRuleList Rules = m_std->GetMaxEDSRules(); for (auto rule : Rules) { std::string exp = rule->m_expressionStr; auto& partEles = xray->GetElementQuantifyData();//find all the elements containing in the particle xray. if (partEles.size() < rule->m_elementList.size()) { continue;// if the size not match then continue. } std::map mapChe; for (auto ch : partEles) { mapChe[ch->GetName()] = ch; } auto& usingEles = rule->m_elementList; bool bMatch=true; for (auto che : usingEles) { auto chemical = mapChe.find(che->GetName()); if (chemical == mapChe.end()) { bMatch = false; break; } } if (!bMatch) continue;//if cann't find the element in the particle's element,then continue. // all the rule's using element are contained in the particle then we replace the element with the percentage value for (std::string s : rule->m_OtherpropertyList) { if (s.find("_elem")!=std::string::npos) { auto val = GetAtomicNoBySortingPercentage(s.c_str(), xray); xmls::ReplaceAll(exp, s, std::to_string(val)); } if (s.find("Element#")!=std::string::npos) { auto val = GetEleNameBySortingPercentage(s.c_str(), xray);//find the "Element#1" and replace it with the real element name. auto& elelist = rule->m_elementList; elelist.push_back(CElementPtr(new CElement(val)));// then replace it in the next step. xmls::ReplaceAll(exp, s, val.GetBuffer()); } } for (auto eleChemistry : rule->m_elementList) { auto e = mapChe[eleChemistry->GetName()]; std::string name = eleChemistry->GetName(); xmls::ReplaceAll(exp, name, std::to_string(e->GetPercentage())); } for (std::string s : rule->m_ImgPropertyList) { auto val = particle->GetImgPropertyValueByName(s.c_str()); xmls::ReplaceAll(exp, s, std::to_string(val)); } bool rst = CalcuExp(exp); if (rst) { MaxEDSTime = rule->m_MaxEDSTime; return true; } else { continue; } } MaxEDSTime = 0; return false; } CString ExpressionClassifyEngine::GetEleNameBySortingPercentage(CString sortingNostr, CPosXrayPtr xrayInfo) { std::map mapPercent; std::map mapSorted; auto eles = xrayInfo->GetElementQuantifyData(); for (auto e : eles) { mapPercent[e->GetPercentage()] = e; } auto itr = --mapPercent.end(); for (int i=0;itr != mapPercent.begin();) { mapSorted.insert(std::pair(i, itr->second)); itr--; i++; } std::string NoStr = sortingNostr; std::vector strs; xmls::SplitString(NoStr, strs, "#"); int No = std::stoi(strs[1]); if (mapSorted.size() > No) { return mapSorted[No]->GetName(); } else { return _T(""); } } double ExpressionClassifyEngine::GetMacValue(CString MacStr) { auto mapconstant = m_std->GetMapConstants(); if (mapconstant.find(MacStr.GetBuffer()) != mapconstant.end()) { return mapconstant[MacStr.GetBuffer()]; } else { return 0.0; } } int ExpressionClassifyEngine::GetAtomicNoBySortingPercentage(CString sortingNostr, CPosXrayPtr xrayInfo) { std::map mapPercent; std::map mapSorted; auto eles = xrayInfo->GetElementQuantifyData(); if (eles.size() == 0) { return 0; } for (auto e : eles) { mapPercent[e->GetPercentage()] = e; } auto itr = --mapPercent.end(); for (int i = 0; itr != mapPercent.begin(); ) { mapSorted.insert(std::pair(i, itr->second)); itr--; i++; } std::string NoStr = sortingNostr; int No=10; if (sortingNostr == "first_elem") No = 0; if (sortingNostr == "second_elem") No = 1; if (sortingNostr == "third_elem") No = 2; if (sortingNostr == "fourth_elem") No = 3; if (sortingNostr == "fifth_elem") No = 4; if (sortingNostr == "sixth_elem") No = 5; if (sortingNostr == "seventh_elem") No =6; if (sortingNostr == "eighth_elem") No = 7; if (sortingNostr == "ninth_elem") No = 8; if (sortingNostr == "tenth_elem") No =9; if (mapSorted.size() > No) { std::string elename = mapSorted[No]->GetName(); CElementPtr ele = CElementPtr(new CElement(elename.c_str())); return ele->GetAtomNum(); } else { return 0; } } CElementChemistriesList ExpressionClassifyEngine::ZeroElementProcess(COTSParticlePtr particle, CPosXrayPtr xray) { auto& originalPartEles = xray->GetElementQuantifyData();//find all the elements containing in the particle xray. CElementChemistriesList partEles; for (auto che : originalPartEles) { auto newChe = CElementChemistryPtr(new CElementChemistry(che.get())); partEles.push_back(newChe); } //make it 100% in total.(so called the "Normalization") double rawPercentage = 0; for (auto ele : partEles) { rawPercentage += ele->GetPercentage(); } for (auto ele : partEles) { ele->SetPercentage(ele->GetPercentage() / rawPercentage * 100); } //zero element process std::map mapChe; for (auto ch : partEles) { mapChe[ch->GetName()] = ch; } ZeroElementRuleList Rules = m_std->GetZeroRules(); for (auto rule : Rules) { std::string exp = rule->GetExpressionStr(); if (partEles.size() < rule->GetUsingElementList().size()) { continue;// if the size not match then continue. } auto& usingEles = rule->GetUsingElementList(); bool bMatch = true; for (auto che : usingEles) { auto chemical = mapChe.find(che->GetName()); if (chemical == mapChe.end()) { bMatch = false; break;//if cann't find the element in the particle's element,then continue. } } if (bMatch == false) continue; // all the rule's using elements are contained in the particle then we replace the element with the percentage value for (std::string s : rule->GetOtherpropertyList()) { if (s.find("_elem")!=std::string::npos) { auto val = GetAtomicNoBySortingPercentage(s.c_str(), xray); xmls::ReplaceAll(exp, s, std::to_string(val)); } if (s.find("Element#")!=std::string::npos) { auto val = GetEleNameBySortingPercentage(s.c_str(), xray);//find the "Element#1" and replace it with the real element name. auto elelist = rule->GetUsingElementList(); elelist.push_back(CElementPtr(new CElement(val)));// then replace it in the next step. rule->SetUsingElementList(elelist); xmls::ReplaceAll(exp, s, val.GetBuffer()); } } for (auto eleChemistry : rule->GetUsingElementList()) { auto e = mapChe.find(eleChemistry->GetName()); if (e != mapChe.end()) { std::string name = eleChemistry->GetName(); xmls::ReplaceAll(exp, name, std::to_string((*e).second->GetPercentage())); } } for (std::string s : rule->GetImgPropertyList()) { auto val = particle->GetImgPropertyValueByName(s.c_str()); xmls::ReplaceAll(exp, s, std::to_string(val)); } for (int i = 0; i < 10; i++) { std::string macStr = "MAC#" + std::to_string(i); if (exp.find(macStr) != std::string::npos) { auto val = GetMacValue(macStr.c_str());//find the "Mac#1" and replace it with the real element name. xmls::ReplaceAll(exp, macStr, std::to_string(val)); } } bool rst = CalcuExp(exp); if (rst) { auto itr = std::find_if(partEles.begin(), partEles.end(), [rule](CElementChemistryPtr ele) {return ele->GetName() == CString(rule->GetZeroElementName().c_str()); }); if (itr != partEles.end()) { //partEles.erase(itr);//if satisfied the condition then erase the element(zero the element). (*itr)->SetPercentage(0);//if satisfied the condition then set element percentage to 0(zero the element). double sumPercentage=0; for (auto ele : partEles) { sumPercentage += ele->GetPercentage(); } for (auto ele : partEles) { if (sumPercentage != 0) { ele->SetPercentage(ele->GetPercentage() / sumPercentage * 100); } } } } else { continue; } } particle->GetXrayInfo()->SetElementQuantifyData(partEles);//set the particle's xray element quantify data to the new partEles. return partEles; } void ExpressionClassifyEngine::ProcessAllPropertiesWithParticleData(std::string& exp, std::map& mapChemistrys, PartSTDRuleItemPtr itm, COTSParticlePtr particle ) { // process the special property name such as "first_elem" and "Element#1" etc. auto xray = particle->GetXrayInfo(); for (std::string s : itm->GetUsingOtherpropertyList()) { if (s.find("_elem") != std::string::npos) { auto val = GetAtomicNoBySortingPercentage(s.c_str(), xray); xmls::ReplaceAll(exp, s, std::to_string(val)); } if (s.find("Element#") != std::string::npos) { auto val = GetEleNameBySortingPercentage(s.c_str(), xray);//find the "Element#1" and replace it with the real element name. auto elelist = itm->GetKeyElementList(); elelist.push_back(CElementPtr(new CElement(val)));// then replace it in the next step. itm->SetKeyElementList(elelist); xmls::ReplaceAll(exp, s, val.GetBuffer()); } } //process the element property for (auto eleChemistry : itm->GetAllSortedEleList()) { auto e = mapChemistrys.find(eleChemistry->GetName().GetBuffer()); if (e != mapChemistrys.end()) { std::string name = eleChemistry->GetName(); xmls::ReplaceAll(exp, name, std::to_string(e->second->GetPercentage())); } else { std::string name = eleChemistry->GetName(); xmls::ReplaceAll(exp, name, "0"); } } //process the image property for (std::string s : itm->GetUsingImgPropertyNameList()) { auto val = particle->GetImgPropertyValueByName(s.c_str()); xmls::ReplaceAll(exp, s, std::to_string(val)); } //process the "true" keyword. if (exp.find("true") != std::string::npos) { xmls::ReplaceAll(exp, "true", "(1=1)"); } //process the "false" keyword. if (exp.find("false") != std::string::npos) { xmls::ReplaceAll(exp, "false", "(1=0)"); } //process the contant value for (int i = 0; i < 10; i++) { std::string macStr = "MAC#" + std::to_string(i); if (exp.find(macStr) != std::string::npos) { auto val = GetMacValue(macStr.c_str());//find the "Mac#1" and replace it with the real element name. xmls::ReplaceAll(exp, macStr, std::to_string(val)); } } } void ExpressionClassifyEngine::ProcessImgPropertiesWithParticleData(std::string& exp, PartSTDRuleItemPtr itm, COTSParticlePtr particle) { //process the image property for (std::string s : itm->GetUsingImgPropertyNameList()) { auto val = particle->GetImgPropertyValueByName(s.c_str()); xmls::ReplaceAll(exp, s, std::to_string(val)); } //process the "true" keyword. if (exp.find("true") != std::string::npos) { xmls::ReplaceAll(exp, "true", "(1=1)"); } //process the "false" keyword. if (exp.find("false") != std::string::npos) { xmls::ReplaceAll(exp, "false", "(1=0)"); } //process the constant value for (int i = 0; i < 10; i++) { std::string macStr = "MAC#" + std::to_string(i); if (exp.find(macStr) != std::string::npos) { auto val = GetMacValue(macStr.c_str());//find the "Mac#1" and replace it with the real element name. xmls::ReplaceAll(exp, macStr, std::to_string(val)); } } } bool ExpressionClassifyEngine::ZeroElementProcess(COTSParticlePtr particle) { auto chems = ZeroElementProcess(particle, particle->GetXrayInfo()); particle->GetXrayInfo()->SetElementQuantifyData(chems); return true; } bool ExpressionClassifyEngine::ClassifyBySpectrum(COTSParticlePtr particle, CPosXrayPtr xray) { return false; } bool ExpressionClassifyEngine::ClassifyByExpressionTemporarySpectrum(COTSParticlePtr particle, CPosXrayPtr xray) { PartSTDRuleItemList ruleItems = m_std->GetSTDRuleItems(); for (auto itm : ruleItems) { if (itm->GetIsElementAnalysis() == false) { auto sim = itm->CalculateSimilarity(xray); if (sim > 0.90) { particle->SetType(OTS_PARTICLE_TYPE::IDENTIFIED); particle->SetClassifyId(itm->GetID()); particle->SetColor(itm->GetColor()); particle->SetClassifyName(itm->GetName()); particle->SetHardness(itm->GetHardness()); particle->SetDensity(itm->GetDensity()); particle->SetConductivity(itm->GetElectrical_conductivity()); particle->SetGroupId(itm->GetGrpID()); particle->SetGroupColor(itm->GetGrpColor()); particle->SetGroupName(itm->GetGrpName()); break; } } } return true; } bool ExpressionClassifyEngine::ClassifyIncA(COTSParticlePtr particle, int SteelTech, CPosXrayPtr xray) { return false; } OTSClassifyEngine::CLEEnginePtr GetParticleEngine(std::string a_libName) { static CLEEnginePtr engine; static std::string libName=""; if (engine == NULL || libName != a_libName) { engine = CLEEnginePtr(new ExpressionClassifyEngine(a_libName)); libName = a_libName; if (!engine->Init()) { return NULL; } } return engine; } }