#pragma once #include "stdafx.h" #include "OTSBrukerImpl.h" #include "3Parties\dibapi.h" #include "BrukerSPXFileMgr.h" #include "ControllerHelper.h" #include namespace OTSController { unsigned int DEFAULT_MAX_WAIT_TIME_COLLECT_COUNTS = 5000; const CString DllXMLFileName = "./Config/ProData/HardwareConfig.xml"; // constructor COTSBrukerImpl::COTSBrukerImpl() : m_bInit(false) , m_psServerName() , m_bSEMInst(false) , m_bScannerInst(false) , m_bXRAyControllerInst(false) , m_psRTSpectrumBuffer() , m_nClientID(0) , m_bSEMExternal(false) , m_nSPU(FIRST_DETECTOR_ID) , m_bConnected(false) , m_pSpectrumHead(NULL) , m_bDoQuantification(false) , m_bShowQuantificationSpectrum(false) { LogTrace(__FILE__,__LINE__,_T("Bruker Implement Controller created")); } // destructor COTSBrukerImpl::~COTSBrukerImpl() { // close client if necessary if (m_bConnected) { CloseClient(); } m_psServerName.reset(); m_psRTSpectrumBuffer.reset(); LogTrace(__FILE__, __LINE__, _T("Bruker Implement Controller released.")); } // COTSBrukerImpl methods // public // initialization BOOL COTSBrukerImpl::Init(CONTROL_TYPE a_nControlType, BOOL a_b32Bite /*=TRUE*/) { //m_bInit is the dll loading flag,so there's no need to free it manually , it'll be release when the the whole process is complete.(gsp) if (!m_bInit) { // calculate Bruker client dll name CString strBruckerDllName = ""; this->GetLoadDllName(strBruckerDllName); // load Bruker client dll name succeed LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::Init: bruker client dll name: %s"), strBruckerDllName); m_bInit = BrukerDll::LoadEspritAPI((/*_T("OTSCPPDll\\") +*/ strBruckerDllName).GetBuffer()); // load Bruker client dll OK? if (!m_bInit) { // failed to load bruker client dll AfxMessageBox(_T("cann't load Bruker dll! name:" + strBruckerDllName)); LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::Init: failed to load Bruker Client Dll , Dll Name: %s"), strBruckerDllName); //exit(0); return false; } } // control type? switch (a_nControlType) { // SEM case CONTROL_TYPE::BRUKER_SEM: { m_bSEMInst = TRUE; } break; // scanner case CONTROL_TYPE::BRUKER_SCAN: { m_bScannerInst = TRUE; } break; // x-ray control case CONTROL_TYPE::BRUKER_XRAY: { m_bXRAyControllerInst = TRUE; } break; default: { // invalid control type, something wrong LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::Init: invalid control type.")); return FALSE; } break; } return TRUE; } BOOL COTSBrukerImpl::Connect() { if (!m_bConnected) { if (QueryBrukerServers() && OpenClient()) { LogTrace(__FILE__, __LINE__, "open bruker client success!"); if (!m_psRTSpectrumBuffer) { m_psRTSpectrumBuffer.reset(new char[(int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE]); } memset(m_psRTSpectrumBuffer.get(), 0, (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE); // ok, return true m_bConnected = true; } else { m_bConnected = false; } } return m_bConnected; } BOOL COTSBrukerImpl::DisConnect() { if (m_bConnected) { CloseClient(); m_bConnected = false; } return true; } void COTSBrukerImpl::SetExpectCount(int expectCount) { m_expectCount = expectCount; } int COTSBrukerImpl::GetExpectCount() { return m_expectCount; } // SEM functions // SEM Data (mag, KV and working distance) BOOL COTSBrukerImpl::GetSEMData(double& a_dMagnification, double& a_dHighVoltage, double& a_dWorkingDistance) { // get SEM data (mag, KV and working distance) double dMagnification, dHighVoltage, dWorkingDistance; if (BrukerDll::GetSEMData(m_nClientID, dMagnification, dHighVoltage, dWorkingDistance) != 0) { // failed to call get SEM data method (mag, KV and working distance) LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetSEMData: failed to call GetSEMBCData client id is %d"), m_nClientID); return FALSE; } a_dMagnification = dMagnification; a_dHighVoltage = dHighVoltage; a_dWorkingDistance = dWorkingDistance; // ok, return TRUE return TRUE; } BOOL COTSBrukerImpl::SetSEMData(double a_dMagnification, double a_dHighVoltage, double a_dWorkingDistance) { if (BrukerDll::SetSEMData(m_nClientID, a_dMagnification, a_dHighVoltage, a_dWorkingDistance) != 0) { // failed to call set SEM data method (mag, KV and working distance) LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSEMData: failed to call GetSEMBCData client id = %d"), m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } // SEM BC Data (brightness and contrast) BOOL COTSBrukerImpl::GetSEMBCData(double& a_dBrightness, double& a_dContrast) { double dBrightness = 0, dContrast = 0; if (BrukerDll::GetSEMBCData(m_nClientID, dBrightness, dContrast) != 0) { // failed to call get SEM data method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetBrightness: failed to call GetSEMBCData client id is %d"), m_nClientID); return FALSE; } a_dBrightness = dBrightness; a_dContrast = dContrast; // ok, return TRUE return TRUE; } BOOL COTSBrukerImpl::SetSEMBCData(double a_dBrightness, double a_dContrast) { // set SEM data if (BrukerDll::SetSEMBCData(m_nClientID, a_dBrightness, a_dContrast) != 0) { // failed to call set SEM data method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetBrightness: failed to call SetSEMBCData client id is %d"), m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } // get Probe Current BOOL COTSBrukerImpl::GetProbeCurrent(double& a_dKV) { // get Probe Current if (BrukerDll::GetSEMProbeCurrent(m_nClientID, a_dKV) != 0) { // failed to call GetSEMSpotSize method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::GetProbeCurrent: failed to call GetSEMProbeCurrent method, client id = %d", m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } BOOL COTSBrukerImpl::SetProbeCurrent(double a_dKV) { // set Probe Current if (BrukerDll::SetSEMProbeCurrent(m_nClientID, a_dKV) != 0) { // failed to call GetSEMSpotSize method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::SetProbeCurrent: failed to call SetSEMProbeCurrent method, client id = %d", m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } // spot size BOOL COTSBrukerImpl::GetSEMSpotSize(double& a_dSpotSize) { // get spot size if (BrukerDll::GetSEMSpotSize(m_nClientID, a_dSpotSize)!=0) { // failed to call GetSEMSpotSize method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::GetSpotSize: failed to call GetSEMSpotSize method, client id = %d", m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } BOOL COTSBrukerImpl::SetSEMSpotSize(double a_dSpotSize) { // set spot size if (BrukerDll::SetSEMSpotSize(m_nClientID, a_dSpotSize)!=0) { // failed to call SetSEMSpotSize method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::SetSEMSpotSize: failed to call SetSEMSpotSize method, client id = %d", m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } // stage data BOOL COTSBrukerImpl::GetSEMStageData( double& a_dPositionX, double& a_dPositionY, double& a_dPositionZ, double& a_dTilt, double& a_dRotation) { // get stage data double dPositionX, dPositionY, dPositionZ, dTilt, dRotation; if (BrukerDll::GetSEMStageData(m_nClientID, dPositionX, dPositionY, dPositionZ, dTilt, dRotation)!=0) { // failed to call GetSEMStageData method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::GetSEMStageData: failed to call GetSEMStageData method, client id = %d", m_nClientID); return FALSE; } a_dPositionX = dPositionX; a_dPositionY = dPositionY; a_dPositionZ = dPositionZ; a_dTilt = dTilt; a_dRotation = dRotation; // ok return TRUE return true; } BOOL COTSBrukerImpl::SetSEMStageData( double a_dPositionX, double a_dPositionY, double a_dPositionZ, double a_dTilt, double a_dRotation) { // set stage data if (BrukerDll::SetSEMStageData(m_nClientID, a_dPositionX, a_dPositionY, a_dPositionZ, a_dTilt, a_dRotation) != 0) { // failed to call SetSEMStageData method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::GetSEMStageData: failed to call SetSEMStageData method, client id = %d", m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } // external on/off BOOL COTSBrukerImpl::SetSEMExternalOn(void) { // set external on if (BrukerDll::SetSEMExternalOn(m_nClientID) == 0) { m_bSEMExternal = true; LogWarn(__FILE__, __LINE__, _T("SetExternal On")); } else { // failed to call SetSEMExternalOn method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::SetSEMExternalOn: failed to call SetSEMExternalOn method, client id = %d", m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } // set SEM external off // return true if success BOOL COTSBrukerImpl::SetSEMExternalOff(void) { // set external off if (BrukerDll::SetSEMExternalOff(m_nClientID)==0) { m_bSEMExternal = false; LogWarn(__FILE__, __LINE__, _T("SetExternal Off")); } else { // failed to call SetSEMExternalOn method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::SetSEMExternalOff: failed to call SetSEMExternalOff method, client id = %d", m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } // get scan Mode BOOL COTSBrukerImpl::GetExternalScanMode(long& a_nScanMode) { a_nScanMode = (m_bSEMExternal) ? BRUKER_SCAN_MODE_EXTERNAL_ON : BRUKER_SCAN_MODE_EXTERNAL_OFF; return TRUE; } // set SEM off BOOL COTSBrukerImpl::SwitchSEMOff(BOOL a_bHTValue, BOOL a_bBeamCurrent, BOOL a_bBeamBlank) { // turn high tension off if (!a_bHTValue) { if (BrukerDll::SwitchSEMOff(m_nClientID, true, false, false)!=0) { // failed to call sSwitchSEMOff method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::SetHTOnOff: failed to call sSwitchSEMOff (HV) method, client id = %d", m_nClientID ); return FALSE; } } else if(a_bBeamCurrent) { if (BrukerDll::SwitchSEMOff(m_nClientID, false, true, false)!=0) { // failed to call sSwitchSEMOff method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::SetHTOnOff: failed to call sSwitchSEMOff (Beam Current) method, client id = %d", m_nClientID ); return FALSE; } } else if(a_bBeamBlank) { if (BrukerDll::SwitchSEMOff(m_nClientID, false, false, true)!=0) { // failed to call sSwitchSEMOff method LogErrorTrace(__FILE__, __LINE__, "COTSBrukerImpl::SetHTOnOff: failed to call sSwitchSEMOff (Beam Blank) method, client id = %d", m_nClientID ); return FALSE; } } // ok, return TRUE return TRUE; } // image configuration BOOL COTSBrukerImpl::ImageGetConfiguration( DWORD& a_nWidth, DWORD& a_nHeight, DWORD& a_nAverage, BYTE& a_bCh1, BYTE& a_bCh2) { // get image configuration uint32_t nWidth; uint32_t nHeight; uint32_t nAverage; bool bCh1; bool bCh2; if (BrukerDll::ImageGetConfiguration(m_nClientID, nWidth, nHeight,nAverage, bCh1, bCh2)!=0) { // failed to call ImageGetConfiguration method LogErrorTrace(__FILE__, __LINE__, "ImageGetConfiguration::ImageGetConfiguration: failed to call ImageGetConfiguration method, client id = %d", m_nClientID); return FALSE; } a_nWidth = nWidth; a_nHeight = nHeight; a_nAverage = nAverage; a_bCh1 = bCh1; a_bCh2 = bCh2; // ok, return TRUE return TRUE; } BOOL COTSBrukerImpl::ImageSetConfiguration( DWORD a_nWidth, DWORD a_nHeight, DWORD a_nAverage, BYTE a_bCh1, BYTE a_bCh2) { // set image configuration if (BrukerDll::ImageSetConfiguration(m_nClientID, a_nWidth, a_nHeight, a_nAverage, a_bCh1, a_bCh2) != 0) { // failed to call ImageSetConfiguration method LogErrorTrace(__FILE__, __LINE__, "ImageGetConfiguration::ImageSetConfiguration: failed to call ImageSetConfiguration method, client id = %d", m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } // Acquire Image CBSEImgPtr COTSBrukerImpl::AcquireImage() { try { // set external on if (!SetSEMExternalOn()) { // failed to call SetSEMExternalOn method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::AcquireImage: failed to call SetSEMExternalOn method.")); return CBSEImgPtr(); } // Get the image config so we can allocate enough memory DWORD nWidth = 0; DWORD nHeight = 0; DWORD nAverage; BYTE bCh1; BYTE bCh2; if (!ImageGetConfiguration(nWidth, nHeight, nAverage, bCh1, bCh2)) { // failed to call ImageGetConfiguration method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::AcquireImage: failed to call ImageGetConfiguration method.")); return CBSEImgPtr(); } // SEM info BrukerDll::TRTImageInfoEx imgInfo; BrukerDll::PRTImageInfoEx oImageInfo=&imgInfo; // the buffer returned is a bitmap stream, i.e. it contains the header information as well int32_t nImageSize = nWidth * nHeight + 20000; std::vector vecImage(nImageSize, 0); BYTE showProgress = false; if (BrukerDll::ImageAquireImage(m_nClientID, 1, showProgress, &vecImage[0], nImageSize, oImageInfo) != 0) { // failed to call ImageAquireImage method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::AcquireImage: failed to call ImageAquireImage, client id is %d"), m_nClientID); return CBSEImgPtr(); } LPBITMAPFILEHEADER pHeader = (LPBITMAPFILEHEADER)&vecImage[0]; LPBITMAPINFOHEADER pInfoHeader = (LPBITMAPINFOHEADER)(pHeader + 1); LPBYTE lpb = FindDIBBits(pInfoHeader); CRect r = CRect(0, 0, nWidth, nHeight); // Bruker acquires an upside-down image. Flip the image here. CBSEImgPtr poBseImage(new CBSEImg(r)); poBseImage->InitImageData(nWidth, nHeight); BYTE* pImageData = poBseImage->GetImageDataPointer(); // turn bInverseImage to FALSE if don't need to do flip BOOL bInverseImage = TRUE; if (bInverseImage) { // copy image upside down for (DWORD i = 0; i < nHeight; ++i) { LPBYTE pTarget = pImageData + i * nWidth; LPBYTE pSource = lpb + (nHeight - 1 - i) * nWidth; memcpy(pTarget, pSource, nWidth); } } else { long nActImageSize = nWidth * nHeight; memcpy(pImageData, lpb, nActImageSize); } // return BSE image return poBseImage; } catch (const std::exception&) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::AcquireImage exception")); } finally{ // turn SEM to external off if (!SetSEMExternalOff()) { // failed to call SetSEMExternalOn method LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::AcquireImage: failed to call SetSEMExternalOff method.")); } } // error, return nullptr return nullptr; } // set image point (move beam to position) // CPoint& a_oPoint offside the image top left point (pixel) BOOL COTSBrukerImpl::ImageSetPoint(const CPoint& a_oPoint) { // image set point if (BrukerDll::ImageSetPoint(m_nClientID, (DWORD)a_oPoint.x, (DWORD)a_oPoint.y) != 0) { // failed to call ImageSetPoint method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ImageSetPoint: failed to call ImageSetPoint, client id is %d"), m_nClientID); return FALSE; } // ok, return TRUE return TRUE; } // x-ray functions /// get live time float COTSBrukerImpl::GetLiveTime() { // safety check ASSERT(m_pSpectrumHead); if (!m_pSpectrumHead) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("GetLiveRealTime::ImageSetPoint: invalid m_pSpectrumHead.")); return 0.0; } // NOTE: m_pSpectrumHead will set when spectra are collected and needs to be set to NULL // after live time is collected float fRet = (float)m_pSpectrumHead->LifeTime / (float)1000.0; // ms to second m_pSpectrumHead = NULL; return fRet; } BOOL COTSBrukerImpl::GetLiveRealTime(float& a_dLiveTime, float& a_dRealTime) { // safety check ASSERT(m_pSpectrumHead); if (!m_pSpectrumHead) { // error, invalid m_pSpectrumHead. LogErrorTrace(__FILE__, __LINE__, _T("GetLiveRealTime::ImageSetPoint: invalid m_pSpectrumHead.")); return FALSE; } // NOTE: m_pSpectrumHead will set when spectra are collected and needs to be set to NULL // after live time is collected a_dLiveTime = (float)m_pSpectrumHead->LifeTime / (float)1000.0; // ms to second a_dRealTime = (float)m_pSpectrumHead->RealTime / (float)1000.0; // ms to second m_pSpectrumHead = NULL; // ok, return TRUE return TRUE; } // collect spectrum data // this method needs to be called after beam has been set to right position by ImageSetPoint method BOOL COTSBrukerImpl::CollectSpectrum( DWORD a_nMilliseconds, long* a_pXRayData, DWORD a_nBufferSize) { // input check ASSERT(a_pXRayData); if (!(a_pXRayData)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectSpectrum: invalid a_pXRayData.")); return FALSE; } // set buffer to 0 memset(a_pXRayData, 0, sizeof(long) * a_nBufferSize); // start x ray measurement if (!SpectrumRealTimeMeasurement(a_nMilliseconds)) { // failed to call SpectrumRealTimeMeasurement method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectSpectrum: failed to call SpectrumRealTimeMeasurement method.")); return FALSE; } if (m_bDoQuantification) { // quantify the spectrum LogInfoTrace(__FILE__,__LINE__,_T("QuantifySpectrum")); char* pcMethod = "Default";//"Default";// "Automatic"; char* pcParams = "ResultType=quantification"; char cResult[(int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE]; memset(cResult, 0, (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE); if (!QuantifySpectrum(pcMethod, pcParams, cResult, (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) { LogErrorTrace(__FILE__,__LINE__,_T("failed to call QuantifySpectrum method")); return FALSE; } LogTrace(__FILE__,__LINE__,_T("Result: %s"), CControllerHelper::CharToString(cResult)); // convert the result char to string CString strResult = CControllerHelper::CharToString(cResult); LogTrace(__FILE__, __LINE__, _T("Result: %s"), strResult); } // read spectrum if (!ReadSpectrum()) { // failed to call ReadSpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectSpectrum: failed to call ReadSpectrum method.")); return FALSE; } // copy spectrum if (!CopySpectrum(a_pXRayData, a_nBufferSize)) { // failed to call CopySpectrum LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectSpectrum: failed to call CopySpectrum method.")); return FALSE; } // ok. return TRUE return TRUE; } BOOL COTSBrukerImpl::QuantifySpectrumOut(DWORD a_nMilliseconds, long* a_pXRayData, DWORD a_nBufferSize, CElementChemistriesList& a_listElementChemistries) { // input check ASSERT(a_pXRayData); if (!(a_pXRayData)) { LogErrorTrace(__FILE__, __LINE__, _T("QuantifySpectrum::CollectSpectrum: invalid a_pXRayData.")); return FALSE; } // set buffer to 0 memset(a_pXRayData, 0, sizeof(long) * a_nBufferSize); // start x ray measurement if (!SpectrumRealTimeMeasurement(a_nMilliseconds)) { // failed to call SpectrumRealTimeMeasurement method LogErrorTrace(__FILE__, __LINE__, _T("QuantifySpectrum::CollectSpectrum: failed to call SpectrumRealTimeMeasurement method.")); return FALSE; } // quantify the spectrum LogInfoTrace(__FILE__, __LINE__, _T("QuantifySpectrum")); char* pcMethod = "Default";// "Automatic"; char* pcParams = "ResultType=quantification"; char cResult[(int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE]; memset(cResult, 0, (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE); if (!QuantifySpectrum(pcMethod, pcParams, cResult, (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) { LogErrorTrace(__FILE__, __LINE__, _T("failed to call QuantifySpectrum method")); return FALSE; } LogTrace(__FILE__, __LINE__, _T("Result: %s"), CControllerHelper::CharToString(cResult)); // convert the result char to string CString strResult = CControllerHelper::CharToString(cResult); LogTrace(__FILE__, __LINE__, _T("Result: %s"), strResult); // separate the result string to element chemistry string std::vector listStrElementChemistries = CControllerHelper::SplitString(strResult, _T("\n")); for (auto strElementChemistry : listStrElementChemistries) { CElementChemistryPtr oElementChemistryData; if (GetElementChemistryData(*oElementChemistryData.get(), strElementChemistry)) { a_listElementChemistries.push_back(oElementChemistryData); } } // read spectrum if (!ReadSpectrum()) { // failed to call ReadSpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectSpectrum: failed to call ReadSpectrum method.")); return FALSE; } // copy spectrum if (!CopySpectrum(a_pXRayData, a_nBufferSize)) { // failed to call CopySpectrum LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectSpectrum: failed to call CopySpectrum method.")); return FALSE; } // ok. return TRUE return TRUE; } // quantify the spectrum in buffer BOOL COTSBrukerImpl::QuantifySpectrum(char* a_pcMethod, char* a_pcParams, char* a_pcResultBuffer, long a_nBufferSize) { // input check ASSERT(a_pcMethod); if (!a_pcParams) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifySpectrum: invalid a_pcMethod.")); return FALSE; } ASSERT(a_pcParams); if (!a_pcParams) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifySpectrum: invalid a_pcParams.")); return FALSE; } ASSERT(a_pcResultBuffer); if (!a_pcResultBuffer) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifySpectrum: invalid a_pcResultBuffer.")); return FALSE; } // quantify the spectrum in buffer if (BrukerDll::QuantifySpectrum(m_nClientID, 1, a_pcMethod, a_pcParams, a_pcResultBuffer, a_nBufferSize) != 0) { // failed to call QuantifySpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifySpectrum:Call QuantifySpectrum failed: client id is %d."), m_nClientID); return false; } // ok. return TRUE return TRUE; } //BOOL COTSBrukerImpl::CollectXRayPoints(CPosXrayList& a_listXrayPois, DWORD a_nACTimeMS) //{ // // do nothing if points list is empty // if (a_listXrayPois.empty()) // { // // points list is empty // LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPoints: poits list is empty.")); // return TRUE; // } // // turn SEM to external // if (!SetSEMExternalOn()) // { // // failed to call SetSEMExternalOn method // LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPoints: failed to call SetSEMExternalOn method.")); // return FALSE; // } // // create array of BrukerSegment // long nCollectCount = (long)a_listXrayPois.size(); // boost::scoped_array segmentArray(new BrukerDll::TSegment[nCollectCount]); // for (int i = 0; i < nCollectCount; ++i) // { // CPoint poi = a_listXrayPois[i]->GetPosition(); // segmentArray[i].Y = poi.y; // segmentArray[i].XStart = poi.x; // segmentArray[i].XCount = 1; // } // // ask bruker to collect a set of x ray data // //if (!StartPointListMeasurement(nCollectCount, segmentArray, a_nACTimeMS)) // //{ // // // failed to call StartPointListMeasurement method // // LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPoints: failed to call StartPointListMeasurement method.")); // // return FALSE; // //} // if (BrukerDll::StartPointListMeasurement(m_nClientID, m_nSPU, nCollectCount, segmentArray, a_nACTimeMS) != 0) // { // LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartFeatureListMeasurement:Call StartFeatureListMeasurement failed: client id is %d"), m_nClientID); // return FALSE; // } // // get the specs for a_listXrayPois // if (!ReadXRayPoints(a_listXrayPois, a_nACTimeMS)) // { // // failed to call ReadXRayPoints method // LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPoints: failed to call ReadXRayPoints method.")); // return FALSE; // } // // return TRUE; //} // collect x ray points (area scan) //BOOL COTSBrukerImpl::CollectXRayPointsByFeatures(std::vector& a_vXPoints, std::vector& a_vFeatures, DWORD a_nACTimeMS) //{ // // do nothing if points list is empty // if (a_vXPoints.empty()) // { // // points list is empty // LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures: poits list is empty.")); // return TRUE; // } // // lists size check // if (a_vXPoints.size() != a_vFeatures.size()) // { // LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures:Feature size(%d) doesn't match xray point size(%d)"), a_vFeatures.size(), a_vXPoints.size()); // return FALSE; // } // // set SEM to external // if (!SetSEMExternalOn()) // { // // failed to call SetSEMExternalOn method // LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures: failed to call SetSEMExternalOn method.")); // return FALSE; // } // // create array of BrukerSegment // long nCollectCount = (long)a_vXPoints.size(); // long nTotalPixelCount = 0; // SHORT* pixelTimes=new SHORT[nCollectCount]; // BrukerDll::TFeatureData* features=new BrukerDll::TFeatureData[nCollectCount]; // std::vector extraSegments; // for (size_t i = 0; i < a_vXPoints.size(); i++) // { // features[i].SegmentCount = (long)a_vFeatures[i].SegmentCount; // if (features[i].SegmentCount > 0) // { // int segCount = features[i].SegmentCount; // auto ofeature = a_vFeatures[i]; // features->Segments = new BrukerDll::TSegment[segCount]; // for (int j = 0; j < segCount; j++) // { // features->Segments[j].XStart = ofeature.pSegment[j].XStart; // features->Segments[j].XCount = ofeature.pSegment[j].XCount; // features->Segments[j].Y = ofeature.pSegment[j].Y; // } // // //features[i].Segments = &a_vFeatures[i].pSegment; // // calculate pixel time // int nPixelCount = 0; // for (int j = 0; j < features[i].SegmentCount; j++) // { // nPixelCount += features[i].Segments[j].XCount; // } // //SHORT pt= (SHORT)(a_nACTimeMS * 1000 / nPixelCount); // pixelTimes[i] = (SHORT)(a_nACTimeMS * 1000 / nPixelCount); // nTotalPixelCount += nPixelCount; // } // else // { // // will generate according to the x-ray position // // this shouldn't happen // extraSegments.push_back(BrukerDll::TSegment()); // extraSegments[extraSegments.size() - 1].XStart = a_vXPoints[i]->GetPosition().x; // extraSegments[extraSegments.size() - 1].Y = a_vXPoints[i]->GetPosition().y; // features[i].SegmentCount = 1; // features[i].Segments = &extraSegments[extraSegments.size() - 1]; // //SHORT pt = (SHORT)(a_nACTimeMS * 1000); // pixelTimes[i] = (SHORT)(a_nACTimeMS * 1000); // } // } // // ask bruker to collect a set of x-ray data // //if (!StartFeatureListMeasurement(nCollectCount, features.get(), pixelTimes.get())) // //{ // // // failed to call StartFeatureListMeasurement method // // LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures: failed to call StartFeatureListMeasurement method.")); // // return FALSE; // //} // if (BrukerDll::StartFeatureListMeasurement(m_nClientID, m_nSPU, nCollectCount, features, &pixelTimes) != 0) // { // LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartFeatureListMeasurement:Call StartFeatureListMeasurement failed: client id is %d"), m_nClientID); // return FALSE; // } // // get the specs for a_vXPoints // if (!ReadXRayPointsByFeature(a_vXPoints, a_nACTimeMS)) // { // // failed to call ReadXRayPointsByFeature method // LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures: failed to call ReadXRayPointsByFeature method.")); // return FALSE; // } // return TRUE; //} BOOL COTSBrukerImpl::ReadXRayPoints(CPosXrayList& a_listXrayPois, const DWORD a_nACTimeMS) { // point list is empty? if (a_listXrayPois.empty()) { // doing nothing if point list is empty LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints: point list (a_listXrayPois) is empty")); return TRUE; } long nCollectCount = (long)a_listXrayPois.size(); // get the specs for a_vXPoints static DWORD nChannelData[(int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS]; for (int i = 0; i < nCollectCount; ++i) { // cleanup data storage memset(nChannelData, 0, sizeof(DWORD) * (int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS); if (m_bDoQuantification) { // quantify the spectrum char* pcMethod = "Default";//"Default";// "Automatic"; char* pcParams = "ResultType=quantification"; char cResult[10000]; memset(cResult, 0, 10000); if (BrukerDll::QuantifyPointListSpectrum(m_nClientID, i, pcMethod, pcParams, cResult, 10000, (BrukerDll::PRTSpectrumHeaderRec)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints failed to call QuantifyPointListSpectrum method, error code %d"), -1); } CElementChemistriesList vElement = CElement::ExtractElementChemistrys(CControllerHelper::CharToString(cResult)); } // get spectrum data of a point bool success = GetPointListSpectrum(i, (long*)nChannelData); if (!success) { // error CPoint poi = a_listXrayPois[i]->GetPosition(); LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints:Call GetPointListSpectrum failed : index = %d(x : %d, y : %d)"), i, poi.x, poi.y); return FALSE; } // set spectrum data for the x-ray point a_listXrayPois[i]->SetXrayData(nChannelData); } // We have seen rare instances where StartPointListMeasurement returns some unexpected empty // spectra. (We can expect spectra to be empty if we measure in a hole due to charging in the // BSE image, but on some occasions we see some empty spectra within areas of a measurement // that otherwise look ok. We have no explanation for this and can't replicate it.) // In these scenarios we want to fall back to a single point measurement to see if it will // collect something valid. // Only if we haven't had an actual bruker error for (int i = 0; i < nCollectCount; ++i) { // check spectrum DWORD nTatolXrayCount = a_listXrayPois[i]->GetTotalCount(); if (nTatolXrayCount < 20) { // captured an empty spectrum CPoint poi = a_listXrayPois[i]->GetPosition(); LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints:Collected low count spectrum(%d counts), index = %d(x:%d, y : %d) This could be caused by charging."), nTatolXrayCount, i, poi.x, poi.y); // try to redo x-ray collection at the position memset(nChannelData, 0, sizeof(DWORD) * (int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS); if (!CollectOneXRayPoint(poi, a_nACTimeMS, (long*)nChannelData, (int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS)) { // error //LogError(_T("Call CollectOneXRayPoint failed: index = %d(x:%d, y:%d)"), // i, poi.x, poi.y); LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints: Call CollectOneXRayPoint failed: index = %d(x:%d, y:%d)"), i, poi.x, poi.y); return FALSE; } // set spectrum with new spectrum a_listXrayPois[i]->SetXrayData(nChannelData); nTatolXrayCount = a_listXrayPois[i]->GetTotalCount(); if (nTatolXrayCount < 20) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints:Single point spectrum still low count (%d counts), index = %d(x:%d, y:%d.) This could be caused by charging."), nTatolXrayCount, i, poi.x, poi.y); } else { LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints:Single point spectrum collected successfully (%d counts), index = %d(x:%d, y:%d.)"), nTatolXrayCount, i, poi.x, poi.y); } } } // ok, return true return TRUE; } BOOL COTSBrukerImpl::ReadXRayPointsByFeature(std::vector& a_vXPoints, const DWORD /*a_nACTimeMS*/) { // point list is empty? if (a_vXPoints.empty()) { // doing nothing if point list is empty LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPointsByFeature: point list is empty")); // ok, return true return TRUE; } long nCollectCount = (long)a_vXPoints.size(); // get the specs for a_vXPoints static DWORD nChannelData[(int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS]; for (int i = 0; i < nCollectCount; ++i) { // cleanup data storage memset(nChannelData, 0, sizeof(DWORD) * (int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS); // get spectrum data of a point bool success = GetFeatureListSpectrum(i, (long*)nChannelData); if (!success) { // error CPoint poi = a_vXPoints[i]->GetPosition(); LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPointsByFeature:Call GetFeatureListSpectrum failed: index = %d(x:%d, y:%d)"), i, poi.x, poi.y); return FALSE; } // set spectrum data for the x-ray point a_vXPoints[i]->SetXrayData(nChannelData); } //ok, return true return TRUE; } BOOL COTSBrukerImpl::ReadXRayPointsByFeature(CPosXrayList& a_vXPoints, const DWORD a_nACTimeMS) { // point list is empty? if (a_vXPoints.empty()) { // point list is empty LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPointsByFeature: point list is empty")); // ok, return true return TRUE; } long nCollectCount = (long)a_vXPoints.size(); // get the specs for a_vXPoints static DWORD nChannelData[(int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS]; for (int i = 0; i < nCollectCount; ++i) { // cleanup data storage memset(nChannelData, 0, sizeof(DWORD) * (int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS); // get spectrum data of a point bool success = GetFeatureListSpectrum(i, (long*)nChannelData); if (!success) { // error CPoint poi = a_vXPoints[i]->GetPosition(); LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPointsByFeature:Call GetFeatureListSpectrum failed: index = %d(x:%d, y:%d)"), i, poi.x, poi.y); return FALSE; } // set spectrum data for the x-ray point a_vXPoints[i]->SetXrayData(nChannelData); } // ok, return true return TRUE; } // protected // query servers BOOL COTSBrukerImpl::QueryBrukerServers(void) { // query servers long nBufferSize = (long)BRUKER_PARAM::BUF_LENGTH; m_psServerName.reset(new char[(int)BRUKER_PARAM::BUF_LENGTH]); memset(m_psServerName.get(), 0, nBufferSize); int ret = BrukerDll::QueryServers(m_psServerName.get(), nBufferSize); if ( ret!= 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QueryServers: failed to call QueryServers method.")); return FALSE; } // ok, return TRUE return TRUE; } // Open Client // return true if success BOOL COTSBrukerImpl::OpenClient(void) { // first attempt to open client bool bStartNew = FALSE; bool bGUI = FALSE; BOOL bConnected = FALSE; auto bRet = BrukerDll::OpenClient(m_psServerName.get(), "edx", "edx", bStartNew, bGUI, m_nClientID);//static_cast(bStartNew) //CheckConnection(bConnected); if (bRet) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::OpenClient: call OpenClient failed at the first attempt.")); bConnected = FALSE; } else { bConnected = TRUE; } // double check the connection if client id is zero if (m_nClientID == 0) { // check if connection is OK if(BrukerDll::CheckConnection(m_nClientID)!=0) { // try to open client again if there is no connection // second attempt to open client bRet = BrukerDll::OpenClient(m_psServerName.get(), "edx", "edx", static_cast(bStartNew), static_cast(bGUI), m_nClientID); if (bRet) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::OpenClient: call OpenClient failed at the second attempt.")); bConnected = false; } } } /*if (!bRet) { m_bConnected = true; }*/ // return method return flag m_bConnected = bConnected; return m_bConnected; } //BOOL COTSBrukerImpl::OpenClient(char* a_sServerName, char* a_sUserName, char* a_sPassword, BYTE a_nStartNew, BYTE a_bGUI, uint32_t& a_nClientID) //{ // // // open client // int32_t bRet = BrukerDll::OpenClient(a_sServerName, a_sUserName, a_sPassword, a_nStartNew, a_bGUI, a_nClientID); // if (bRet!=0) // { // // LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::OpenClient: failed to open client dll.")); // return false; // } // return true; //} // check detector states and set m_nSPU // Bruker四个有一个盒子,盒子共接4个探头 BOOL COTSBrukerImpl::SetSPU(void) { long nCombineValue = 0; BOOL bCombine = FALSE; // check if the first detector is OK BOOL bFirst = FALSE; uint32_t nMaxEnergy1; if (!CheckDetectorState(FIRST_DETECTOR_ID, bFirst, nMaxEnergy1)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: failed to call CheckDetectorState method (first).")); return FALSE; } if (bFirst) { nCombineValue = m_nSPU = FIRST_DETECTOR_COM; LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: find first.")); } // check if the second detector is OK BOOL bSecond = FALSE; uint32_t nMaxEnergy2; if (!CheckDetectorState(SECOND_DETECTOR_ID, bSecond, nMaxEnergy2)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: failed to call CheckDetectorState method (second).")); return FALSE; } if (bSecond) { m_nSPU = SECOND_DETECTOR_ID; if (nCombineValue != 0) { bCombine = TRUE; m_nSPU = FIRST_DETECTOR_ID; } nCombineValue += SECOND_DETECTOR_COM; LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: find second.")); } // the third detector is OK BOOL bThird = FALSE; uint32_t nMaxEnergy3; if (!CheckDetectorState(THIRD_DETECTOR_ID, bThird, nMaxEnergy3)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: failed to call CheckDetectorState method (third).")); return FALSE; } if (bThird) { m_nSPU = THIRD_DETECTOR_ID; if (nCombineValue != 0) { bCombine = TRUE; m_nSPU = FIRST_DETECTOR_ID; } nCombineValue += THIRD_DETECTOR_COM; LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: find third.")); } // the fourth detector is OK BOOL bFourth = FALSE; uint32_t nMaxEnergy4; if (!CheckDetectorState(FOURTH_DETECTOR_ID, bFourth, nMaxEnergy4)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: failed to call CheckDetectorState method (fourth).")); return FALSE; } if (bFourth) { m_nSPU = FOURTH_DETECTOR_ID; if (nCombineValue != 0) { bCombine = TRUE; m_nSPU = FIRST_DETECTOR_ID; } nCombineValue += FOURTH_DETECTOR_COM; LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: find fourth.")); } // combine the two detectors if more than one active detectors. BOOL bRet = FALSE; if (bCombine) { bRet = BrukerDll::CombineSpectrometer(m_nClientID, nCombineValue)==0; LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: find combined.")); } else { bRet = (nCombineValue != 0); if (!bRet) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: no detactor.")); } } LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: result is %d."), bRet); // method return flag return bRet; } // check detector State BOOL COTSBrukerImpl::CheckDetectorState(long a_nDetectorId, BOOL& a_bState, uint32_t& a_nMaxEnergy) { // get spectrum configuration uint32_t nPulseThroughput; a_bState = BrukerDll::GetSpectrometerConfiguration(m_nClientID, a_nDetectorId, a_nMaxEnergy, nPulseThroughput); // ok, return TRUE return TRUE; } // Close Client // return true if success BOOL COTSBrukerImpl::CloseClient(void) { LogTrace(__FILE__, __LINE__, _T("Close Bruker client...")+ CString(std::to_string(m_nClientID).c_str())); if (BrukerDll::CloseClient(m_nClientID) != 0) { LogErrorTrace(__FILE__, __LINE__, " COTSBrukerImpl::CloseClient failed "); return FALSE; } return TRUE; } /// collect a x ray point /// input: CPoint a_oPoi, // DWORD a_nLifeTimeMilliSeconds, // long* a_pXRayData, // DWORD a_nBufferSize, // CollectOneXRayPoint /// return true if success BOOL COTSBrukerImpl::CollectOneXRayPoint( const CPoint& a_oPoi, DWORD a_nLifeTimeMilliSeconds, long* a_pXRayData, DWORD a_nBufferSize, bool a_bSetHeadStruc) { // move beam to the point if (!ImageSetPoint(a_oPoi)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectOneXRayPoint:Call ImageSetPoint failed: at position [%d, %d]"), a_oPoi.x, a_oPoi.y); return FALSE; } // collect a x-ray if (!CollectSpectrum(a_nLifeTimeMilliSeconds, a_pXRayData, a_nBufferSize)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectOneXRayPoint:Call CollectSpectrum failed : at position[%d, %d]"), a_oPoi.x, a_oPoi.y); return FALSE; } // ok, return true return TRUE; } BOOL COTSBrukerImpl::StartSpectrumMeasurement() { DWORD nRealTime = 0; // Success? if (BrukerDll::StartSpectrumMeasurement(m_nClientID, m_nSPU, nRealTime) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::::StartSpectrumMeasurement:Call StartSpectrumMeasurement failed: client id is %d"), m_nClientID); return FALSE; } // ok, return true return TRUE; } // call IsSpectrumMeterRunning // return true if success BOOL COTSBrukerImpl::IsSpectrumMeasureRunning(BOOL& a_bRunning) { double nState; double nPulseRate; bool bRunning; if (BrukerDll::GetSpectrumMeasureState(m_nClientID, 1, bRunning, nState, nPulseRate) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::IsSpectrumMeterRunning:Call GetSpectrumMeasureState failed: client id is %d"), m_nClientID); return FALSE; } a_bRunning = (BOOL)bRunning; // ok, return true return TRUE; } // call StopSpectrumMeter // return true if success BOOL COTSBrukerImpl::StopSpectrumMeasure(void) { if (BrukerDll::StopSpectrumMeasurement(m_nClientID, 1) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StopSpectrumMeter:Call StopSpectrumMeasurement failed: client id is %d"), m_nClientID); return FALSE; } // ok, return true return TRUE; } BOOL COTSBrukerImpl::ReadSpectrum(long* a_pXRayData, DWORD a_nBufferSize) { // read spectrum if (!ReadSpectrum()) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::Read Spectrum failed.")); return FALSE; } // copy spectrum if (!CopySpectrum(a_pXRayData, a_nBufferSize)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadSpectrum:Copy Spectrum failed.")); return FALSE; } // ok, return true return TRUE; } // get quantification method name strings (automatic only) BOOL COTSBrukerImpl::GetQuantificationMethods(std::vector& a_vMethods) { // automatic methods only bool AUTOMATIC_ONLY = true; // char buffer size const long CHAR_BUFFER_SIZE = 4096 * 100; // char buffer char cBuffer[CHAR_BUFFER_SIZE]; int32_t nBufferSize = CHAR_BUFFER_SIZE; // get quantification method name strings if (BrukerDll::GetQuantificationMethods(m_nClientID, AUTOMATIC_ONLY, cBuffer, nBufferSize) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("Call GetQuantificationMethods failed: client id is %d"), m_nClientID); return FALSE; } // get the quantification method name strings CString strMethodsNames = CControllerHelper::CharToString(cBuffer); LogTrace(__FILE__, __LINE__, _T("Result: %s"), strMethodsNames); // clear the method strings list a_vMethods.clear(); // separate the method strings a_vMethods = CControllerHelper::SplitString(strMethodsNames, _T("\n")); // ok, return true return TRUE; } BOOL COTSBrukerImpl::QuantifyXrayPoint(CPosXray* a_pXRayPoint, CString a_strMethodName) { ASSERT(a_pXRayPoint); if (!a_pXRayPoint) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifyXrayPoint:x-ray point is empty, return")); return FALSE; } // method name validation a_strMethodName.Trim(); ASSERT(!a_strMethodName.IsEmpty()); if (a_strMethodName.IsEmpty()) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifyXrayPoint:method name is empty, return")); return FALSE; } CString sFilePathName = GetQuantificationSpectrumPathName(); // export CBrukerSPXFileMgr spxFileHelpers; if (!spxFileHelpers.ExportXrayPoint(sFilePathName, _T("Quantification"), a_pXRayPoint)) { LogErrorTrace(__FILE__,__LINE__,_T("Save quantification file(%s) failed."), sFilePathName); return FALSE; } CElementChemistriesList vElementChemistry; if (!QuantifySpectrumFile(sFilePathName, a_strMethodName, vElementChemistry)) { LogErrorTrace(__FILE__,__LINE__,_T("Quantify spectrum by method %s from file(%s) failed."), a_strMethodName, sFilePathName); return FALSE; } a_pXRayPoint->SetElementQuantifyData(vElementChemistry); // ok, return true return true; } BOOL COTSBrukerImpl::QuantifyPosXrayPointOnLine(CPosXrayPtr a_vXRayPart) { char* pcMethod = "Default";//"Default";//"Automatic"; char* pcParams = "ResultType=quantification"; char cResult[10000]; memset(cResult, 0, 10000); if (BrukerDll::QuantifyPointListSpectrum(m_nClientID, a_vXRayPart->GetIndex(), pcMethod, pcParams, cResult, 10000, (BrukerDll::PRTSpectrumHeaderRec)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifyPosXrayPointOnLine failed to call QuantifyPointListSpectrum method at index %d, error code %d"), a_vXRayPart->GetIndex(), -1); return false; } CElementChemistriesList listElement = CElement::ExtractElementChemistrys(CControllerHelper::CharToString(cResult)); a_vXRayPart->SetElementQuantifyData(listElement); return true; } BOOL COTSBrukerImpl::QuantifySpectrumFile(LPCTSTR a_sFilePathName, CString a_strMethodName, CElementChemistriesList& a_vElementChemistry) { ASSERT(a_sFilePathName); if (!a_sFilePathName) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifySpectrumFile:file path name is not correct, return")); return FALSE; } char sPathName[MAX_PATH]; CControllerHelper::WCharToChar((const wchar_t *)a_sFilePathName, sPathName); if (!LoadSpectrum(sPathName)) { LogErrorTrace(__FILE__,__LINE__,_T("LoadSpectrum from file(%s) failed"), a_sFilePathName); return FALSE; } LogTrace(__FILE__,__LINE__,_T("Loaded spectrum to Bruker from file %s"), a_sFilePathName); if (m_bShowQuantificationSpectrum) { ShowSpectrum(0, "Quantification"); } char cMethod[(int)BRUKER_PARAM::BUF_LENGTH]; CControllerHelper::WCharToChar((const wchar_t *)&a_strMethodName, cMethod); char* pcParams = "ResultType=quantification"; char cResult[(int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE]; memset(cResult, 0, (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE); LogTrace(__FILE__,__LINE__,_T("To QuantifySpectrum")); if (BrukerDll::QuantifySpectrum(m_nClientID, 0, cMethod, pcParams, cResult, (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE) != 0) { LogErrorTrace(__FILE__,__LINE__,_T("Call QuantifySpectrum failed: client id is %d."), m_nClientID); return FALSE; } // convert the result char to string CString strResult = CControllerHelper::CharToString(cResult); LogTrace(__FILE__,__LINE__,_T("Result: %s"), strResult); // separate the result string to element chemistry string std::vector vElementChemistryStrings = CControllerHelper::SplitString(strResult, _T("\n")); for (auto& strElementChemistry : vElementChemistryStrings) { CElementChemistryPtr oElementChemistryData; if (GetElementChemistryData(*oElementChemistryData.get(), strElementChemistry)) { a_vElementChemistry.push_back(oElementChemistryData); } } // ok, return true return TRUE; } RTSpectrumHeaderRec* COTSBrukerImpl::GetSectrumHeader() { // safety check ASSERT(m_psRTSpectrumBuffer); if (!m_psRTSpectrumBuffer) { // error, invalid m_psRTSpectrumBuffer LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetSectrumHeader: invalid m_psRTSpectrumBuffer")); // return nullptr return nullptr; } return (RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(); } // call GetSpectrum // return true if success BOOL COTSBrukerImpl::GetSpectrum(long a_nBufferIndex, BrukerDll::PRTSpectrumHeaderRec a_poSpcHR, long a_nBufferSize) { if (BrukerDll::GetSpectrum(m_nClientID, a_nBufferIndex, a_poSpcHR, a_nBufferSize) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetSpectrum:Call GetSpectrum failed: client id is %d, error code is %d."), m_nClientID); return FALSE; } // ok, return true return TRUE; } BOOL COTSBrukerImpl::LoadSpectrum(char* a_sFilePathName) { // safety check ASSERT(a_sFilePathName); if (!a_sFilePathName) { // invalid a_sFilePathName LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::LoadSpectrum: invalid a_sFilePathName")); return FALSE; } if (BrukerDll::LoadSpectrum(m_nClientID, a_sFilePathName) != 0) { // error, failed to call LoadSpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::LoadSpectrum: failed to call LoadSpectrum method. client id is %d."), m_nClientID); return FALSE; } // ok, return true return TRUE; } // call ReadSpectrum // return true if success BOOL COTSBrukerImpl::ReadSpectrum(void) { if (BrukerDll::ReadSpectrum(m_nClientID, 1) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadSpectrum:Call ReadSpectrum failed: client id is %d"), m_nClientID); return FALSE; } // ok, return true return TRUE; } // put spectrum into Bruker system BOOL COTSBrukerImpl::PutSpectrum(char* a_pBuffer, long a_nBufferSize) { if (BrukerDll::PutSpectrum(m_nClientID, a_pBuffer, a_nBufferSize) != 0) { // error, fail to call PutSpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::PutSpectrum: failed to call PutSpectrum."), m_nClientID); return FALSE; } // ok, return true return TRUE; } BOOL COTSBrukerImpl::CreateSpectrum(char* m_pParamBuffer, BrukerDll::PRTSpectrumHeaderRec a_poSpcHR, char* m_pResultBuffer, int32_t& a_nBufferSize) { // safety check ASSERT(m_pParamBuffer); if (!m_pParamBuffer) { // error, invalid m_pParamBuffer LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CreateSpectrum: invalid m_pParamBuffer")); return FALSE; } ASSERT(a_poSpcHR); if (!a_poSpcHR) { // invalid a_poSpcHR LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CreateSpectrum: invalid a_poSpcHR")); return FALSE; } ASSERT(m_pResultBuffer); if (!m_pResultBuffer) { // error, invalid m_pResultBuffer LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CreateSpectrum: invalid m_pResultBuffer")); return FALSE; } if (BrukerDll::CreateSpectrum(m_pParamBuffer, a_poSpcHR, m_pResultBuffer, a_nBufferSize) != 0) { // error, failed to call CreateSpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CreateSpectrum: failed to call CreateSpectrum method. client id is %d."), m_nClientID); return FALSE; } // ok, return true return TRUE; } BOOL COTSBrukerImpl::ShowSpectrum(long a_nBufferIndex, char* a_pSpectumName) { ASSERT(a_pSpectumName); if (!a_pSpectumName) { // error, invalid a_pSpectumName LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ShowSpectrum: invalid a_pSpectumName")); return FALSE; } if (BrukerDll::ShowSpectrum(m_nClientID, a_nBufferIndex, a_pSpectumName) != 0) { // error, failed to call ShowSpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ShowSpectrum: failed to call ShowSpectrum method. client id is %d."), m_nClientID); return FALSE; } // ok, return true return TRUE; } BOOL COTSBrukerImpl::GetSpectrometerParams(long a_nBufferIndex, char* a_pBuffer, int32_t& a_nBufferSize) { if (BrukerDll::GetSpectrometerParams(m_nClientID, a_nBufferIndex, a_pBuffer, a_nBufferSize) != 0) { // error, failed to call GetSpectrometerParams method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetSpectrometerParams: failed to call GetSpectrometerParams method. client id is %d."), m_nClientID); return FALSE; } // ok, return true return TRUE; } BOOL COTSBrukerImpl::GetElementChemistryData(CElementChemistry& a_oElementChemistryData, CString a_strElementChemistry) { // split element chemistry string std::vector vString = CControllerHelper::SplitString(a_strElementChemistry, _T(",")); // the strings list should has at least three strings long MIN_STRINGs_COUNT = 3; if (MIN_STRINGs_COUNT > (long)vString.size()) { return FALSE; } // name CString strName = vString[0]; strName.Trim(); if (strName.IsEmpty()) { return FALSE; } auto nPos = strName.Find(_T("=")); CString strTempName; if (nPos > 0) { strTempName = strName.Right(strName.GetLength() - nPos - 1); } else { LogErrorTrace(__FILE__,__LINE__,_T("Wrong element name string(%s)"), strName); strTempName = strName.Right(1); } a_oElementChemistryData.SetName(strTempName); // percentage CString strPercentage = vString[2]; strPercentage.Trim(); if (strPercentage.IsEmpty()) { return FALSE; } double dPercentage; if (!CControllerHelper::StringToDouble(strPercentage, dPercentage)) { return FALSE; } a_oElementChemistryData.SetPercentage(dPercentage); // OK return true return TRUE; } // call CopySpectrum // return true if success BOOL COTSBrukerImpl::CopySpectrum(long* a_pXRayData, DWORD a_nBufferSize) { // start x ray measurement if (!GetSpectrum(1, (BrukerDll::PRTSpectrumHeaderRec)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) { // error, failed to call GetSpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl:: failed to call GetSpectrum method.")); return FALSE; } // convert spectrum if (!ConvertSpectrum((RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(), a_pXRayData, a_nBufferSize)) { // error failed to call ConvertSpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::Call ConvertSpectrum failed.")); return FALSE; } // set head struck // always get a spectrum header for exporting quantify header m_pSpectrumHead = (RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(); // ok, return true return TRUE; } // start spectrum life time measurement BOOL COTSBrukerImpl::StartSpectrumLifeTimeMeasurement(DWORD a_nLifeTime) { if (BrukerDll::StartSpectrumLifeTimeMeasurement(m_nClientID, m_nSPU, a_nLifeTime) != 0) { // error, failed to call StartSpectrumLifeTimeMeasurement method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartSpectrumLifeTimeMeasurement: failed to call StartSpectrumLifeTimeMeasurement method. client id is %d"), m_nClientID); return FALSE; } // ok, return true return TRUE; } // call StartSpectrumLifeTimeMeasurement // return true if success BOOL COTSBrukerImpl::SpectrumLifeTimeMeasurement(DWORD a_nLifeTime) { if (!StartSpectrumLifeTimeMeasurement(a_nLifeTime)) { // error failed to call StartSpectrumLifeTimeMeasurement method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumLifeTimeMeasurement: failed to call StartSpectrumLifeTimeMeasurement method.")); return FALSE; } // check to see if the system has finished the action #pragma warning(suppress: 28159) DWORD nStart = GetTickCount(); DWORD nEnd = nStart; BOOL bRunning = TRUE; do { #pragma warning(suppress: 28159) nEnd = GetTickCount(); if (!IsSpectrumMeasureRunning(bRunning)) { // error, failed to call IsSpectrumMeterRunning method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumLifeTimeMeasurement: failed to call IsSpectrumMeterRunning method.")); return FALSE; } } while (nEnd >= nStart && nEnd <= (nStart + a_nLifeTime + 1) && bRunning); // force to stop if system still busy if (bRunning && !StopSpectrumMeasure()) { // error, failed to call stop StopSpectrumMeter method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumLifeTimeMeasurement: failed to call StopSpectrumMeter method.")); return FALSE; } // ok, return true return TRUE; } // Start Spectrum Real Time Measurement BOOL COTSBrukerImpl::StartSpectrumRealTimeMeasurement(DWORD a_nRealTime) { if (BrukerDll::StartSpectrumMeasurement(m_nClientID, m_nSPU, a_nRealTime) != 0) { // error, failed to call StartSpectrumMeasurement method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartSpectrumRealTimeMeasurement: failed to call StartSpectrumMeasurement method. client id is %d."), m_nClientID); return FALSE; } // ok, return true return TRUE; } // call StartSpectrumRealTimeMeasurement // return true if success BOOL COTSBrukerImpl::SpectrumRealTimeMeasurement(DWORD a_nRealTime) { if (!StartSpectrumRealTimeMeasurement(a_nRealTime)) { // error, failed to call StartSpectrumRealTimeMeasurement method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumRealTimeMeasurement: failed to call StartSpectrumRealTimeMeasurement method.")); return FALSE; } // check to see if the system has finished the action #pragma warning(suppress: 28159) DWORD nStart = GetTickCount(); DWORD nEnd = nStart; BOOL bRunning = TRUE; do { #pragma warning(suppress: 28159) nEnd = GetTickCount(); if (!IsSpectrumMeasureRunning(bRunning)) { // error, failed to call IsSpectrumMeterRunning method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumRealTimeMeasurement: failed to call IsSpectrumMeterRunning method.")); return FALSE; } } while (nEnd >= nStart && nEnd <= (nStart + a_nRealTime + 1) && bRunning); // force to stop if system still busy if (bRunning && !StopSpectrumMeasure()) { // error failed to call StopSpectrumMeter method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumRealTimeMeasurementCall: failed to call StopSpectrumMeter method.")); return FALSE; } // ok, return true return TRUE; } BOOL COTSBrukerImpl::SpectrumCountsMeasurement(DWORD a_nTotalCounts, int a_nTimeLimit /*= -1*/) { if (a_nTimeLimit <= 0) { a_nTimeLimit = DEFAULT_MAX_WAIT_TIME_COLLECT_COUNTS; } if (!StartSpectrumMeasurement()) { // error, failed to call StartSpectrumMeasurement method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumCountsMeasurement: failed to call StartSpectrumMeasurement method.")); return FALSE; } // check to see if the system has finished the action #pragma warning(suppress: 28159) DWORD nStartTime = GetTickCount(); DWORD nEndTime = nStartTime; BOOL bRunning = TRUE; do { if (!IsSpectrumMeasureRunning(bRunning)) { // error, failed to call IsSpectrumMeterRunning method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumCountsMeasurement: failed to call IsSpectrumMeterRunning method.")); return FALSE; } if (!bRunning) { // get out if bruker stopped LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumCountsMeasurement: Bruker stopped.")); break; } // read spectrum if (!ReadSpectrum()) { // error, failed to call ReadSpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumCountsMeasurement: failed to call ReadSpectrum method.")); return FALSE; } // get a x ray if (!GetSpectrum(1, (BrukerDll::PRTSpectrumHeaderRec)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) { // error, failed to call GetSpectrum method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumCountsMeasurement: failed to call GetSpectrum(1) method.")); return FALSE; } // quick to check total counts // pcharTemp point to start of whole spectrum char* pcharTemp = (char*)m_psRTSpectrumBuffer.get(); // jump over spectrum head, pcharTemp points to the data block pcharTemp += sizeof(RTSpectrumHeaderRec); // pLongChannels point to the data block long* pLongChannels = (long*)pcharTemp; RTSpectrumHeaderRec* pSpectrumHead = (RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(); int nTotalChannel = pSpectrumHead->ChannelCount; DWORD nTotalPoints = 0; for (int i = 0; i < nTotalChannel; ++i) { nTotalPoints += pLongChannels[i]; } #pragma warning(suppress: 28159) nEndTime = GetTickCount(); if (nTotalPoints >= a_nTotalCounts) { // get out, get enough points LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumCountsMeasurement: Stop collection: Got enough points")); break; } // stop collection if it take too long if (nEndTime > (nStartTime + a_nTimeLimit + 1)) { // get out, took too long LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumCountsMeasurement: Stop collection, took too long.")); break; } } while (bRunning); // force to stop if system still busy if (bRunning && !StopSpectrumMeasure()) { // error, failed to call StopSpectrumMeter method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SpectrumCountsMeasurement: failed to call StopSpectrumMeter method.")); return FALSE; } // ok, return true return TRUE; } BOOL COTSBrukerImpl::ConvertSpectrum(RTSpectrumHeaderRec* a_poSpcHR, long* a_pXRayData, DWORD a_nBufferSize) { // safety check ASSERT(a_poSpcHR); if (!a_poSpcHR) { // error, invalid a_poSpcHR LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ConvertSpectrum: invalid a_poSpcHR.")); return FALSE; } if (!(a_nBufferSize > 0)) { // error, invalid buffer size LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ConvertSpectrum: invalid buffer size.")); return FALSE; } a_poSpcHR->ChannelCount = 4096; ASSERT(a_pXRayData); if (!a_pXRayData) { // error, invalid a_pXRayData LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ConvertSpectrum: invalid a_pXRayData.")); return FALSE; } // calculate zero peak channel long nZeroPeakChannel = 0; const double MIN_CALIBRATION_LIN = 0.000001; if (fabs(a_poSpcHR->CalibrationLin) > MIN_CALIBRATION_LIN) { nZeroPeakChannel = (long)fabs(a_poSpcHR->CalibrationAbs / a_poSpcHR->CalibrationLin); } // check if there are valid data channels if (a_poSpcHR->ChannelCount / 2 <= nZeroPeakChannel) { // error, no channel data; LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ConvertSpectrum: no channel data (nZeroPeakChannel: %i)."), nZeroPeakChannel); return FALSE; } // pcharTemp point to start of whole spectrum char* pcharTemp = (char*)a_poSpcHR; // jump over spectrum head, pcharTemp points to the data block pcharTemp += sizeof(RTSpectrumHeaderRec); // pLongChannels point to the data block long* pLongChannels = (long*)pcharTemp; // calculate zero peak ending channel long nZeroPeakEndingChannel = nZeroPeakChannel; // check if there are valid data channels if (a_poSpcHR->ChannelCount <= nZeroPeakEndingChannel) { // no channel data LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ConvertSpectrum: no channel data nZeroPeakEndingChannel: %i)."), nZeroPeakEndingChannel); return FALSE; } // find the end of the zero peak channel long nPrevCount = pLongChannels[nZeroPeakEndingChannel]; for (long i = 0; i < nZeroPeakChannel && // zero peak ending channel will be less than nZeroPeakChannel * 2 nPrevCount > 0; ++i) { ++nZeroPeakEndingChannel; long nCurrentCount = pLongChannels[nZeroPeakEndingChannel]; long nNextCount = pLongChannels[nZeroPeakEndingChannel + 1]; long nNextNextCountNext = pLongChannels[nZeroPeakEndingChannel + 2]; // if current count == 0 && nNextCount == 0 && nNextNextCountNext == 0 // or current > previous count && nNextCount > nCurrentCount && nNextNextCountNext > nNextCount, then this is if ((nCurrentCount == 0 && nNextCount == 0 && nNextNextCountNext == 0) || (nCurrentCount > nPrevCount && nNextCount > nCurrentCount && nNextNextCountNext > nNextCount)) { // find the zero peak ending channel, get out break; } // the current count will be the nPrevCount = nCurrentCount; } // calculate valid data channel number long nDataChannelNO = a_poSpcHR->ChannelCount - nZeroPeakChannel; // clean zero peak data if (a_poSpcHR->ChannelCount > (nZeroPeakEndingChannel + 1)) { memset(pLongChannels, 0, (nZeroPeakEndingChannel + 1) * sizeof(long)); } // jump over zero peak channels pLongChannels += nZeroPeakChannel; // clean data buffer memset(a_pXRayData, 0, a_nBufferSize * sizeof(long)); // copy data from bruker data buffer to data buffer [blend] double dStep1 = 1.0 / (double)nDataChannelNO; // step size of bruker bin double dStep2 = 1.0 / (double)a_nBufferSize; // step size of bin // blend bruker data for (long i = 0; i < nDataChannelNO; ++i) { // get the bruker bin data long nValue = (pLongChannels[i] > 0) ? pLongChannels[i] : 0; // calculate the bruker bin position double dBinPos = (double)i * dStep1; // calculate bin number on the left side of the position long nLeftBin = (long)(dBinPos / dStep2); // calculate % into left bin double dLeft_Percent = double(nLeftBin + 1) - dBinPos / dStep2; // ((nLeftBin + 1)*dStep2 - dBinPos)/dStep2 // calculate data into the left bin long nValueToLeftBin = (long)((double)nValue * dLeft_Percent + 0.5); // put data into bins a_pXRayData[nLeftBin] += nValueToLeftBin; if ((nLeftBin + 1) < (long)a_nBufferSize) { a_pXRayData[nLeftBin + 1] += (nValue - nValueToLeftBin); } } // ok, return true return TRUE; } // call GetPointListSpectrum // return true if success BOOL COTSBrukerImpl::GetPointListSpectrum(long a_nIndex, long* a_pnSpec) { ASSERT(a_pnSpec); if (!a_pnSpec) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetPointListSpectrum: invalid a_pnSpec.")); return FALSE; } // Success? if (BrukerDll::GetPointListSpectrum(m_nClientID, a_nIndex, (BrukerDll::PRTSpectrumHeaderRec)m_psRTSpectrumBuffer.get(), (long)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE) == 0) { if (!ConvertSpectrum((RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(), a_pnSpec, (DWORD)BRUKER_PARAM::RT_SPECTRUM_CHANNELS)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetPointListSpectrum:Call ConvertSpectrum failed.")); return FALSE; } } else { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetPointListSpectrum:Call GetPointListSpectrum failed: error code is %d."), -1); return FALSE; } return TRUE; } // call GetFeatureListSpectrum // return true if success BOOL COTSBrukerImpl::GetFeatureListSpectrum(long a_nIndex, long* a_pnSpec) { if (!a_pnSpec) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetFeatureListSpectrum:a_pnSpec failed, return")); return FALSE; } // Success? if ((BrukerDll::GetFeatureListSpectrum(m_nClientID, a_nIndex, (BrukerDll::PRTSpectrumHeaderRec)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetFeatureListSpectrum:failed, return")); return FALSE; } // return method return flag if (!ConvertSpectrum((RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(), a_pnSpec, (int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetFeatureListSpectrum: convert spectrum failed, return")); return FALSE; } return TRUE; } // CString COTSBrukerImpl::GetQuantificationSpectrumPathName() { CString sFilePathName = _T("\\QuantificationSpectrum.spx"); return sFilePathName; } BOOL COTSBrukerImpl::GetXRayByPoints(CPosXrayList& a_listXrayPois, DWORD a_nACTimeMS) { try { // do nothing if points list is empty if (a_listXrayPois.empty()) { // points list is empty LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetXRayByPoints: poits list is empty.")); return TRUE; } // create array of BrukerSegment long nCollectCount = (long)a_listXrayPois.size(); boost::scoped_array segmentArray(new BrukerDll::TSegment[nCollectCount]); for (int i = 0; i < nCollectCount; ++i) { CPoint poi = a_listXrayPois[i]->GetPosition(); segmentArray[i].Y = poi.y; segmentArray[i].XStart = poi.x; segmentArray[i].XCount = 1; } if (BrukerDll::StartPointListMeasurement(m_nClientID, m_nSPU, nCollectCount, segmentArray.get(), a_nACTimeMS) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartPointListMeasurement:Call StartPointListMeasurement failed: client id is %d(%d, %d, %d)"), m_nClientID, m_nSPU, nCollectCount, a_nACTimeMS); return FALSE; } // get the specs for a_vXPoints static DWORD nChannelData[(int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS]; for (int i = 0; i < nCollectCount; ++i) { // cleanup data storage memset(nChannelData, 0, sizeof(DWORD) * (int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS); // get spectrum data of a point bool success = GetPointListSpectrum(i, (long*)nChannelData); if (!success) { // error CPoint poi = a_listXrayPois[i]->GetPosition(); LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetXRayPoints:Call GetPointListSpectrum failed : index = %d(x : %d, y : %d)"), i, poi.x, poi.y); return FALSE; } // set spectrum data for the x-ray point a_listXrayPois[i]->SetXrayData(nChannelData); } if (m_bDoQuantification) { QuantifyPosXrayPointsOnLine(a_listXrayPois); } return TRUE; } catch (const std::exception&) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetXRayByPoints: exception.")); } // error, return false return FALSE; } BOOL COTSBrukerImpl::QuantifyPosXrayPointsOnLine(CPosXrayList& a_listXrayPois) { // Fail a_vXPoints is empty if (a_listXrayPois.empty()) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifyPosXrayPointsOnLine: Empty point list given in argument a_oPointList")); return TRUE; } long nCollectCount = (long)a_listXrayPois.size(); // get the specs for a_vXPoints static DWORD nChannelData[(int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS]; for (int i = 0; i < nCollectCount; ++i) { // cleanup data storage memset(nChannelData, 0, sizeof(DWORD) * (int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS); // quantify the spectrum char* pcMethod = "Default";//"Default";//"Automatic"; char* pcParams = "ResultType=quantification"; char cResult[10000]; memset(cResult, 0, 10000); int xraySequence = a_listXrayPois[i]->GetIndex(); if (BrukerDll::QuantifyPointListSpectrum(m_nClientID, xraySequence, pcMethod, pcParams, cResult, 10000, (BrukerDll::PRTSpectrumHeaderRec)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifyPosXrayPointsOnLine failed to call QuantifyPointListSpectrum method at index %d, error code %d"), xraySequence, -1); } CElementChemistriesList listElement = CElement::ExtractElementChemistrys(CControllerHelper::CharToString(cResult)); a_listXrayPois[i]->SetElementQuantifyData(listElement); } return TRUE; } BOOL COTSBrukerImpl::GetXRayByFeatures(CPosXrayList& a_vXPoints, std::vector a_vFeatures, SHORT a_nACTimeMS) { // do nothing if points list is empty if (a_vXPoints.empty()) { // points list is empty LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures: poits list is empty.")); return TRUE; } // lists size check if (a_vXPoints.size() != a_vFeatures.size()) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures:Feature size(%d) doesn't match xray point size(%d)"), a_vFeatures.size(), a_vXPoints.size()); return FALSE; } // create array of BrukerSegment long nCollectCount = (long)a_vXPoints.size(); long nTotalPixelCount = 0; SHORT* pixelTimes=new SHORT[nCollectCount]; BrukerDll::PFeatureDataList features = new BrukerDll::TFeatureData[nCollectCount]; for (size_t i = 0; i < nCollectCount; i++) { BrukerFeature ofeature = a_vFeatures[i]; if (ofeature.SegmentCount > 0) { features[i].SegmentCount = ofeature.SegmentCount; int segCount = features[i].SegmentCount; //auto ofeature = a_vFeatures[i]; features[i].Segments = new BrukerDll::TSegment[segCount]; for (int j = 0; j < segCount; j++) { features[i].Segments[j].XStart = ofeature.pSegment[j].XStart; features[i].Segments[j].XCount = ofeature.pSegment[j].XCount; features[i].Segments[j].Y = ofeature.pSegment[j].Y; } // calculate pixel time int nPixelCount = 0; for (int j = 0; j < ofeature.SegmentCount; j++) { nPixelCount += ofeature.pSegment[j].XCount; } SHORT pt= (SHORT)(ceil((double)a_nACTimeMS * 1000.0 / (double)nPixelCount)); pixelTimes[i] = pt; nTotalPixelCount += nPixelCount; } else { // will generate according to the x-ray position // this shouldn't happen BrukerDll::TSegment* extraSegments=new BrukerDll::TSegment[1]; extraSegments[0].XStart = a_vXPoints[i]->GetPosition().x; extraSegments[0].Y = a_vXPoints[i]->GetPosition().y; extraSegments[0].XCount = 1; features[i].SegmentCount = 1; features[i].Segments = extraSegments; pixelTimes[i] = (SHORT)(a_nACTimeMS * 1000); } } // ask bruker to collect a set of x-ray data if (BrukerDll::StartFeatureListMeasurement(m_nClientID, m_nSPU, nCollectCount, features, pixelTimes) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartFeatureListMeasurement:Call StartFeatureListMeasurement failed: client id is %d"), m_nClientID); return FALSE; } // get the specs for a_vXPoints if (!SetXRayPointsByFeature(a_vXPoints, a_nACTimeMS)) { // failed to call ReadXRayPointsByFeature method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures: failed to call ReadXRayPointsByFeature method.")); return FALSE; } delete[] pixelTimes; delete[] features; return TRUE; } BOOL COTSBrukerImpl::SetXRayPointsByFeature(CPosXrayList& a_vXPoints, const DWORD a_nACTimeMS) { // Fail a_vXPoints is empty if (a_vXPoints.empty()) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPointsByFeature:Empty point list given in argument a_oPointList")); return TRUE; } long nCollectCount = (long)a_vXPoints.size(); // get the specs for a_vXPoints static DWORD nChannelData[(int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS]; for (int i = 0; i < nCollectCount; ++i) { // cleanup data storage memset(nChannelData, 0, sizeof(DWORD) * (int)BRUKER_PARAM::RT_SPECTRUM_CHANNELS); if (m_bDoQuantification) { // quantify the spectrum char* pcMethod = "Default";//"Default";// "Automatic"; char* pcParams = "ResultType=quantification"; char cResult[10000]; int index = a_vXPoints[i]->GetIndex(); memset(cResult, 0, 10000); if (BrukerDll::QuantifyFeatureListSpectrum(m_nClientID, index, pcMethod, pcParams, cResult, 10000, (BrukerDll::PRTSpectrumHeaderRec)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE) != 0) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetXRayPointsByFeature failed to call QuantifyFeatureListSpectrum method, error code %d"), -1); //return FALSE; } CElementChemistriesList listElement = CElement::ExtractElementChemistrys(CControllerHelper::CharToString(cResult)); a_vXPoints[i]->SetElementQuantifyData(listElement); } // get spectrum data of a point bool success = GetFeatureListSpectrum(i, (long*)nChannelData); if (!success) { // error CPoint poi = a_vXPoints[i]->GetPosition(); LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPointsByFeature:Call GetFeatureListSpectrum failed: index = %d(x:%d, y:%d)"), i, poi.x, poi.y); return FALSE; } // set spectrum data for the x-ray point a_vXPoints[i]->SetXrayData(nChannelData); } return TRUE; } BOOL COTSBrukerImpl::GetLoadDllName(CString& csDllName) { tinyxml2::XMLDocument doc; doc.LoadFile(DllXMLFileName);//载入xml文件 xmls::Slo subClass; xmls::xString szS; subClass.Register("Version", &szS); subClass.Register("BrukerDllVersion", &subClass); tinyxml2::XMLElement *rootNode; rootNode = doc.FirstChildElement(RootClassName); subClass.Serialize(false, &doc, rootNode); csDllName = szS.value().c_str(); return true; } }