#pragma once #include "stdafx.h" #include "OTSBrukerImpl.h" #include "3Parties\dibapi.h" #include "BrukerSPXFileMgr.h" #include "ControllerHelper.h" #include #include "OTSImageProcess.h" namespace OTSController { using namespace OTSIMGPROC; 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_pBrukerDllHandle() , 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(); } // memory clean m_pBrukerDllHandle.reset(); 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 on initialtive , it'll be free when the the process complet.(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); // is dll opened? if (!m_pBrukerDllHandle) { // make sure Bruker dll handle clean m_pBrukerDllHandle.reset(new OTSBrukerClientDll); // load Bruker client dll m_bInit = m_pBrukerDllHandle->LoadDll(strBruckerDllName); } // 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; } } // initialized? if (!m_bConnected) { if (QueryServers() && 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; } } // 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: { // check detector states and set m_nSPU if (!SetSPU()) { return FALSE; } m_bXRAyControllerInst = TRUE; } break; default: { // invalid control type, something wrong LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::Init: invalid control type.")); return FALSE; } break; } return m_bConnected; } BOOL COTSBrukerImpl::DisConnect() { if (m_bConnected) { CloseClient(); m_bConnected = false; } return true; } // check connection BOOL COTSBrukerImpl::CheckConnection(BOOL& a_bConnected) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CheckConnection: invalid m_pBrukerDllHandle.")); return FALSE; } // check connection if (m_pBrukerDllHandle->CheckConnection(m_nClientID)) { // connected a_bConnected = TRUE; // ok, return true return TRUE; } else { // connection failed a_bConnected = FALSE; // get error code int nError = m_pBrukerDllHandle->GetLastReturn(); // return TRUE if error code is no connection if (nError == (int)EBrukerErrorCode::ERROR_NO_CONNECTION) { // error, no hardware connected LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CheckConnection: no hardware connected.")); } else { // error, other connect error LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CheckConnection: failed to call CheckConnection method.")); } // connection has something wrong, return false return FALSE; } } // SEM functions // SEM Data (mag, KV and working distance) BOOL COTSBrukerImpl::GetSEMData(double& a_dMagnification, double& a_dHighVoltage, double& a_dWorkingDistance) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetContrast: invalid m_pBrukerDllHandle.")); return FALSE; } // get SEM data (mag, KV and working distance) double dMagnification, dHighVoltage, dWorkingDistance; if (!m_pBrukerDllHandle->GetSEMData(m_nClientID, &dMagnification, &dHighVoltage, &dWorkingDistance)) { // 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) { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetContrast: invalid m_pBrukerDllHandle.")); return FALSE; } // set SEM data (mag, KV and working distance) if (!m_pBrukerDllHandle->SetSEMData(m_nClientID, a_dMagnification, a_dHighVoltage, a_dWorkingDistance)) { // 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) { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetBrightness: invalid m_pBrukerDllHandle.")); return FALSE; } // get SEM data double dBrightness = 0, dContrast = 0; if (!m_pBrukerDllHandle->GetSEMBCData(m_nClientID, &dBrightness, &dContrast)) { // 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) { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetBrightness: invalid m_pBrukerDllHandle.")); return FALSE; } // set SEM data if (!m_pBrukerDllHandle->SetSEMBCData(m_nClientID, a_dBrightness, a_dContrast)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetProbeCurrent: invalid m_pBrukerDllHandle")); return FALSE; } // get Probe Current if (!m_pBrukerDllHandle->GetSEMProbeCurrent(m_nClientID, &a_dKV)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // safety check LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetProbeCurrent: invalid m_pBrukerDllHandle.")); return FALSE; } // set Probe Current if (!m_pBrukerDllHandle->SetSEMProbeCurrent(m_nClientID, a_dKV)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetSEMSpotSize: invalid m_pBrukerDllHandle.")); return FALSE; } // get spot size if (!m_pBrukerDllHandle->GetSEMSpotSize(m_nClientID, &a_dSpotSize)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSEMSpotSize: invalid m_pBrukerDllHandle.")); return FALSE; } // set spot size if (!m_pBrukerDllHandle->SetSEMSpotSize(m_nClientID, a_dSpotSize)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetSEMStageData: invalid m_pBrukerDllHandle.")); return FALSE; } // get stage data double dPositionX, dPositionY, dPositionZ, dTilt, dRotation; if (!m_pBrukerDllHandle->GetSEMStageData(m_nClientID, &dPositionX, &dPositionY, &dPositionZ, &dTilt, &dRotation)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSEMStageData: invalid m_pBrukerDllHandle.")); return FALSE; } // set stage data if (!m_pBrukerDllHandle->SetSEMStageData(m_nClientID, a_dPositionX, a_dPositionY, a_dPositionZ, a_dTilt, a_dRotation)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSEMExternalOn: invalid m_pBrukerDllHandle.")); return FALSE; } // set external on if (m_pBrukerDllHandle->SetSEMExternalOn(m_nClientID)) { 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSEMExternalOff: invalid m_pBrukerDllHandle.")); return FALSE; } // set external off if (m_pBrukerDllHandle->SetSEMExternalOff(m_nClientID)) { 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::GetScanMode(long& a_nScanMode) { a_nScanMode = (m_bSEMExternal) ? BRUKER_SCAN_MODE_EXTERNAL_ON : BRUKER_SCAN_MODE_EXTERNAL_OFF; return TRUE; } // set scan mode BOOL COTSBrukerImpl::SetScanMode(long a_nScanMode) { // method return flag BOOL bRet = FALSE; if (a_nScanMode == BRUKER_SCAN_MODE_EXTERNAL_OFF) { bRet = SetSEMExternalOff(); } else if (!m_bSEMExternal) { bRet = SetSEMExternalOn(); } // return method return flag return bRet; } // set SEM off BOOL COTSBrukerImpl::SwitchSEMOff(BOOL a_bHTValue, BOOL a_bBeamCurrent, BOOL a_bBeamBlank) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SwitchSEMOff: invalid m_pBrukerDllHandle.")); return FALSE; } // turn high tension off if (!a_bHTValue) { if (!m_pBrukerDllHandle->SwitchSEMOff(m_nClientID, true, false, false)) { // 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 (!m_pBrukerDllHandle->SwitchSEMOff(m_nClientID, false, true, false)) { // 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 (!m_pBrukerDllHandle->SwitchSEMOff(m_nClientID, false, false, true)) { // 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) { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ImageGetConfiguration: invalid m_pBrukerDllHandle.")); return FALSE; } // get image configuration DWORD nWidth; DWORD nHeight; DWORD nAverage; BYTE bCh1; BYTE bCh2; if (!m_pBrukerDllHandle->ImageGetConfiguration(m_nClientID, &nWidth, &nHeight, &nAverage, &bCh1, &bCh2)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ImageSetConfiguration: invalid m_pBrukerDllHandle.")); return FALSE; } // set image configuration if (!m_pBrukerDllHandle->ImageSetConfiguration(m_nClientID, a_nWidth, a_nHeight, a_nAverage, a_bCh1, a_bCh2)) { // 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 { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::AcquireImage: invalid m_pBrukerDllHandle.")); // return empty BES image point return CBSEImgPtr(); } // 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 RTImageInfoEx oImageInfo; // the buffer returned is a bitmap stream, i.e. it contains the header information as well long nImageSize = nWidth * nHeight + 20000; std::vector vecImage(nImageSize, 0); BYTE showProgress = false; if (!m_pBrukerDllHandle->ImageAquireImage(m_nClientID, 1, showProgress, &vecImage[0], &nImageSize, &oImageInfo)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ImageSetPoint: invalid m_pBrukerDllHandle.")); return FALSE; } // image set point if (!m_pBrukerDllHandle->ImageSetPoint(m_nClientID, (DWORD)a_oPoint.x, (DWORD)a_oPoint.y)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pSpectrumHead. LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectSpectrum: invalid m_pBrukerDllHandle.")); return FALSE; } // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("QuantifySpectrum::CollectSpectrum: invalid m_pBrukerDllHandle.")); return FALSE; } // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifySpectrum: invalid m_pBrukerDllHandle.")); return FALSE; } // 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 (!m_pBrukerDllHandle->QuantifySpectrum(m_nClientID, 1, a_pcMethod, a_pcParams, a_pcResultBuffer, a_nBufferSize)) { // 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; } // collect x ray points (point scan) BOOL COTSBrukerImpl::CollectXRayPoints(std::vector& a_vXPoints, DWORD a_nACTimeMS) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPoints: invalid m_pBrukerDllHandle.")); return FALSE; } // do nothing if points list is empty if (a_vXPoints.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_vXPoints.size(); //boost::scoped_array segmentArray(new BrukerSegment[nCollectCount]); BrukerSegment* segmentArray(new BrukerSegment[nCollectCount]); for (int i = 0; i < nCollectCount; ++i) { CPoint poi = a_vXPoints[i]->GetPosition(); segmentArray[i].Y = poi.y; segmentArray[i].XStart = poi.x; } // 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; } // get the specs for a_vXPoints if (!ReadXRayPoints(a_vXPoints, a_nACTimeMS)) { // failed to call ReadXRayPoints method LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPoints: failed to call ReadXRayPoints method.")); return FALSE; } delete segmentArray; // ok return TRUE return TRUE; } BOOL COTSBrukerImpl::CollectXRayPoints(CPosXraysList& a_listXrayPois, DWORD a_nACTimeMS) { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPoints: invalid m_pBrukerDllHandle.")); return FALSE; } // 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 BrukerSegment[nCollectCount]); BrukerSegment* segmentArray(new BrukerSegment[nCollectCount]); for (int i = 0; i < nCollectCount; ++i) { CPoint poi = a_listXrayPois[i]->GetPosition(); segmentArray[i].Y = poi.y; segmentArray[i].XStart = poi.x; } // 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; } // 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; } delete segmentArray; // ok return TRUE return TRUE; } // collect x ray points (area scan) BOOL COTSBrukerImpl::CollectXRayPointsByFeatures(std::vector& a_vXPoints, std::vector>& a_vFeatures, DWORD a_nACTimeMS) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures: invalid m_pBrukerDllHandle.")); return FALSE; } // 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; // add by Jieshi 23/08/2017 /*boost::scoped_array pixelTimes(new WORD[nCollectCount]); boost::scoped_array features(new BrukerFeature[nCollectCount]);*/ WORD* pixelTimes(new WORD[nCollectCount]); BrukerFeature* features(new BrukerFeature[nCollectCount]); std::vector extraSegments; for (size_t i = 0; i < a_vXPoints.size(); i++) { features[i].SegmentCount = (long)a_vFeatures[i].size(); if (features[i].SegmentCount > 0) { features[i].pSegment = &a_vFeatures[i][0]; // calculate pixel time int nPixelCount = 0; for (int j = 0; j < features[i].SegmentCount; j++) { nPixelCount += features[i].pSegment[j].XCount; } pixelTimes[i] = (WORD)(a_nACTimeMS * 1000 / nPixelCount); nTotalPixelCount += nPixelCount; } else { // will generate according to the x-ray position // this shouldn't happen extraSegments.push_back(BrukerSegment()); 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].pSegment = &extraSegments[extraSegments.size() - 1]; pixelTimes[i] = (WORD)(a_nACTimeMS * 1000); } } // ask bruker to collect a set of x-ray data if (!StartFeatureListMeasurement(nCollectCount, features, pixelTimes)) { // failed to call StartFeatureListMeasurement method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures: failed to call StartFeatureListMeasurement method.")); 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; } delete pixelTimes; delete features; // ok, return TRUE return TRUE; } BOOL COTSBrukerImpl::ReadXRayPoints(std::vector& a_vXPoints, const DWORD a_nACTimeMS) { // Fail a_vXPoints is empty if (a_vXPoints.empty()) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints 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]; memset(cResult, 0, 10000); if (!m_pBrukerDllHandle->QuantifyPointListSpectrum(m_nClientID, i, pcMethod, pcParams, cResult, 10000, (RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints failed to call QuantifyPointListSpectrum method, error code %d"), m_pBrukerDllHandle->GetLastReturn()); } 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_vXPoints[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_vXPoints[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_vXPoints[i]->GetTotalCount(); if (nTatolXrayCount < 20) { // captured an empty spectrum CPoint poi = a_vXPoints[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_vXPoints[i]->SetXrayData(nChannelData); nTatolXrayCount = a_vXPoints[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); } } } LogInfoTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints end")); return TRUE; } BOOL COTSBrukerImpl::ReadXRayPoints(CPosXraysList& 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 (!m_pBrukerDllHandle->QuantifyPointListSpectrum(m_nClientID, i, pcMethod, pcParams, cResult, 10000, (RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadXRayPoints failed to call QuantifyPointListSpectrum method, error code %d"), m_pBrukerDllHandle->GetLastReturn()); } 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(CPosXraysList& 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::QueryServers(void) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QueryServers: invalid m_pBrukerDllHandle.")); return FALSE; } // 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); if (!m_pBrukerDllHandle->QueryServers(m_psServerName.get(), nBufferSize)) { 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) { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::OpenClient: invalid m_pBrukerDllHandle.")); return FALSE; } // first attempt to open client BOOL bStartNew = FALSE; BOOL bGUI = FALSE; BOOL bRet = 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 first attempt.")); } // double check the connection if client id is zero BOOL bConnected = FALSE; if (m_nClientID == 0) { // check if connection is OK if (!CheckConnection(bConnected)) { // failed to check connection m_bConnected = false; return FALSE; } // try to open client again if there is no connection if (!bConnected) { // second attempt to open client bRet = 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.")); m_bConnected = false; } } } if (bRet) { m_bConnected = true; } // return method return flag return bRet; } BOOL COTSBrukerImpl::OpenClient(char* a_sServerName, char* a_sUserName, char* a_sPassword, BYTE a_nStartNew, BYTE a_bGUI, DWORD* a_nClientID) { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::OpenClient: invalid m_pBrukerDllHandle.")); return FALSE; } // open client BOOL bRet = m_pBrukerDllHandle->OpenClient(a_sServerName, a_sUserName, a_sPassword, a_nStartNew, a_bGUI, a_nClientID); if (!bRet) { // failed to open the client // get error code long nRet = m_pBrukerDllHandle->GetLastReturn(); if (nRet == -201) { // -201 -- there is an opened instance. bRet = TRUE; m_bConnected = FALSE; // FALSE, do not close the interface when the controller is deleted LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::OpenClient: client dll is in used.")); } else { bRet = FALSE; LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::OpenClient: failed to open client dll.")); } } return bRet; } // check detector states and set m_nSPU // Bruker四个有一个盒子,盒子共接4个探头 BOOL COTSBrukerImpl::SetSPU(void) { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetSPU: invalid m_pBrukerDllHandle.")); return FALSE; } // combine value long nCombineValue = 0; BOOL bCombine = FALSE; // check if the first detector is OK BOOL bFirst = FALSE; long 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; long 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; long 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; long 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 = m_pBrukerDllHandle->CombineSpectrometer(m_nClientID, nCombineValue); 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, long& a_nMaxEnergy) { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CheckDetectorState: invalid m_pBrukerDllHandle.")); return FALSE; } // get spectrum configuration DWORD nPulseThroughput; a_bState = m_pBrukerDllHandle->GetSpectrometerConfiguration(m_nClientID, a_nDetectorId, a_nMaxEnergy, &nPulseThroughput); // ok, return TRUE return TRUE; } // Close Client // return true if success BOOL COTSBrukerImpl::CloseClient(void) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { LogErrorTrace(__FILE__, __LINE__, " COTSBrukerImpl::CloseClient: invalid m_pBrukerDllHandle"); return FALSE; } LogTrace(__FILE__, __LINE__, _T("Close Bruker client...")+ CString(std::to_string(m_nClientID).c_str())); if (!m_pBrukerDllHandle->CloseClient(m_nClientID)) { 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() { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartSpectrumMeasurement: invalid m_pBrukerDllHandle")); return FALSE; } DWORD nRealTime = 0; // Success? if (!m_pBrukerDllHandle->StartSpectrumMeasurement(m_nClientID, m_nSPU, nRealTime)) { 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::IsSpectrumMeterRunning(BOOL& a_bRunning) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::IsSpectrumMeterRunning:m_pBrukerDllHandle failed, return")); return FALSE; } double nState; double nPulseRate; bool bRunning; if (!m_pBrukerDllHandle->GetSpectrumMeasureState(m_nClientID, 1, &bRunning, &nState, &nPulseRate)) { 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StopSpectrumMeter:m_pBrukerDllHandle failed, return")); return FALSE; } if (!m_pBrukerDllHandle->StopSpectrumMeasurement(m_nClientID, 1)) { 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetQuantificationMethods: invalid m_pBrukerDllHandle")); return FALSE; } // automatic methods only bool AUTOMATIC_ONLY = true; // char buffer size const long CHAR_BUFFER_SIZE = 4096 * 100; // char buffer char cBuffer[CHAR_BUFFER_SIZE]; long nBufferSize = CHAR_BUFFER_SIZE; // get quantification method name strings if (!m_pBrukerDllHandle->GetQuantificationMethods(m_nClientID, AUTOMATIC_ONLY, cBuffer, &nBufferSize)) { 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifyXrayPoint: invalid m_pBrukerDllHandle")); return FALSE; } 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::QuantifySpectrumFile(LPCTSTR a_sFilePathName, CString a_strMethodName, CElementChemistriesList& a_vElementChemistry) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::QuantifyXrayPoint: invalid m_pBrukerDllHandle")); return FALSE; } 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 (!m_pBrukerDllHandle->QuantifySpectrum(m_nClientID, 0, cMethod, pcParams, cResult, (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) { 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, RTSpectrumHeaderRec*a_poSpcHR, long a_nBufferSize) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetSpectrum: invalid m_pBrukerDllHandle")); return FALSE; } if (!m_pBrukerDllHandle->GetSpectrum(m_nClientID, a_nBufferIndex, a_poSpcHR, a_nBufferSize)) { 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; } ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::LoadSpectrum: invalid m_pBrukerDllHandle")); return FALSE; } if (!m_pBrukerDllHandle->LoadSpectrum(m_nClientID, a_sFilePathName)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ReadSpectrum: invalid m_pBrukerDllHandle")); return FALSE; } if (!m_pBrukerDllHandle->ReadSpectrum(m_nClientID, 1)) { 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::PutSpectrum: invalid m_pBrukerDllHandle")); return FALSE; } if (!m_pBrukerDllHandle->PutSpectrum(m_nClientID, a_pBuffer, a_nBufferSize)) { // 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, RTSpectrumHeaderRec* a_poSpcHR, char* m_pResultBuffer, long& 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; } ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CreateSpectrum: invalid m_pBrukerDllHandle")); return FALSE; } if (!m_pBrukerDllHandle->CreateSpectrum(m_pParamBuffer, a_poSpcHR, m_pResultBuffer, &a_nBufferSize)) { // 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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ShowSpectrum: invalid m_pBrukerDllHandle")); return FALSE; } ASSERT(a_pSpectumName); if (!a_pSpectumName) { // error, invalid a_pSpectumName LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::ShowSpectrum: invalid a_pSpectumName")); return FALSE; } if (!m_pBrukerDllHandle->ShowSpectrum(m_nClientID, a_nBufferIndex, a_pSpectumName)) { // 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, long& a_nBufferSize) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetSpectrometerParams: invalid m_pBrukerDllHandle")); return FALSE; } if (!m_pBrukerDllHandle->GetSpectrometerParams(m_nClientID, a_nBufferIndex, a_pBuffer, &a_nBufferSize)) { // 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, (RTSpectrumHeaderRec*)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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartSpectrumLifeTimeMeasurement: invalid m_pBrukerDllHandle")); return FALSE; } if (!m_pBrukerDllHandle->StartSpectrumLifeTimeMeasurement(m_nClientID, m_nSPU, a_nLifeTime)) { // 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 (!IsSpectrumMeterRunning(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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartSpectrumRealTimeMeasurement: invalid m_pBrukerDllHandle")); return FALSE; } if (!m_pBrukerDllHandle->StartSpectrumMeasurement(m_nClientID, m_nSPU, a_nRealTime)) { // 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 (!IsSpectrumMeterRunning(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 (!IsSpectrumMeterRunning(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, (RTSpectrumHeaderRec*)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) { // safety check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetPointListSpectrum: invalid m_pBrukerDllHandle.")); return FALSE; } ASSERT(a_pnSpec); if (!a_pnSpec) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetPointListSpectrum: invalid a_pnSpec.")); return FALSE; } // Success? if (m_pBrukerDllHandle->GetPointListSpectrum(m_nClientID, a_nIndex, (RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(), (long)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) { 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 { long hr = m_pBrukerDllHandle->GetLastReturn(); if (hr == (long)EBrukerErrorCode::ERROR_INVALID_RESULT_DATA) // ERROR_INVALID_RESULT_DATA (-106) usually occurs during an out of memory situation { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetPointListSpectrum:Call GetPointListSpectrum failed: invalid data.")); } else { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetPointListSpectrum:Call GetPointListSpectrum failed: error code is %d."), hr); } return FALSE; } return TRUE; } // call GetFeatureListSpectrum // return true if success BOOL COTSBrukerImpl::GetFeatureListSpectrum(long a_nIndex, long* a_pnSpec) { if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetFeatureListSpectrum:m_pBrukerDllHandle failed, return")); return FALSE; } if (!a_pnSpec) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetFeatureListSpectrum:a_pnSpec failed, return")); return FALSE; } // Success? if (!(m_pBrukerDllHandle->GetFeatureListSpectrum(m_nClientID, a_nIndex, (RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE))) { 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; } // call StartPointListMeasurement // return true if success BOOL COTSBrukerImpl::StartPointListMeasurement( DWORD a_nSegmentCount, BrukerSegment* a_poSegment, DWORD m_nMilliseconds) { ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartPointListMeasurement:m_pBrukerDllHandle failed, return")); return FALSE; } ASSERT(a_poSegment); if (!a_poSegment) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartPointListMeasurement:a_poSegment failed, return")); return FALSE; } if (!m_pBrukerDllHandle->StartPointListMeasurement(m_nClientID, m_nSPU, a_nSegmentCount, a_poSegment, m_nMilliseconds)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartPointListMeasurement:Call StartPointListMeasurement failed: client id is %d(%d, %d, %d)"), m_nClientID, m_nSPU, a_nSegmentCount, m_nMilliseconds); return FALSE; } return TRUE; } // call StartFeatureListMeasurement // return true if success BOOL COTSBrukerImpl::StartFeatureListMeasurement( DWORD a_nFeatureCount, BrukerFeature* a_poFeature, WORD* a_pwdPixelTimes) { ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartFeatureListMeasurement:m_pBrukerDllHandle failed, return")); return FALSE; } ASSERT(a_poFeature); if (!a_poFeature) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartFeatureListMeasurement:a_poFeature failed, return")); return FALSE; } if (!a_pwdPixelTimes) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartFeatureListMeasurement:a_pwdPixelTimes failed, return")); return FALSE; } if (!m_pBrukerDllHandle->StartFeatureListMeasurement(m_nClientID, m_nSPU, a_nFeatureCount, a_poFeature, a_pwdPixelTimes)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::StartFeatureListMeasurement:Call StartFeatureListMeasurement failed: client id is %d"), m_nClientID); return FALSE; } return TRUE; } // CString COTSBrukerImpl::GetQuantificationSpectrumPathName() { CString sFilePathName = _T("\\QuantificationSpectrum.spx"); return sFilePathName; } BOOL COTSBrukerImpl::GetXRayByPoints(CPosXraysList& a_listXrayPois, DWORD a_nACTimeMS) { try { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetXRayByPoints: invalid m_pBrukerDllHandle.")); return FALSE; } // 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(); BrukerSegment* segmentArray(new BrukerSegment[nCollectCount]); for (int i = 0; i < nCollectCount; ++i) { CPoint poi = a_listXrayPois[i]->GetPosition(); segmentArray[i].Y = poi.y; segmentArray[i].XStart = poi.x; } // 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; } // get the specs for a_listXrayPois if (!SetXRayPoints(a_listXrayPois, a_nACTimeMS)) { // failed to call ReadXRayPoints method LogTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPoints: failed to call ReadXRayPoints method.")); return FALSE; } delete[] segmentArray; // ok return TRUE return TRUE; } catch (const std::exception&) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::GetXRayByPoints: exception.")); } // error, return false return FALSE; } BOOL COTSBrukerImpl::SetXRayPoints(CPosXraysList& a_listXrayPois, const DWORD a_nACTimeMS) { // Fail a_vXPoints is empty if (a_listXrayPois.empty()) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetXRayPoints 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); // 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); std::vector eleList; for each (CElementChemistryPtr var in a_listXrayPois[i]->GetElementQuantifyData()) { eleList.push_back(var->GetName()); } bool isFilter = true; if (eleList.size() != 0) { isFilter = COTSImageProcess::FindPeaks(nChannelData, eleList); } if (m_bDoQuantification && isFilter) { // quantify the spectrum char* pcMethod = "Oxides";//"Default";//"Automatic";//Oxides char* pcParams = "ResultType=quantification"; char cResult[10000]; memset(cResult, 0, 10000); if (!m_pBrukerDllHandle->QuantifyPointListSpectrum(m_nClientID, i, pcMethod, pcParams, cResult, 10000, (RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetXRayPoints failed to call QuantifyPointListSpectrum method at index %d, error code %d"), i, m_pBrukerDllHandle->GetLastReturn()); //return FALSE; } //LogErrorTrace(__FILE__, __LINE__, cResult); CElementChemistriesList listElement = CElement::ExtractElementChemistrys(CControllerHelper::CharToString(cResult)); a_listXrayPois[i]->SetElementQuantifyData(listElement); } else { CElementChemistriesList listElement; a_listXrayPois[i]->SetElementQuantifyData(listElement); } } // 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::SetXRayPoints: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, call CollectOneXRayPoint failed LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetXRayPoints: 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); //return FALSE; } 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::GetXRayByFeatures(CPosXraysList& a_vXPoints, std::vector a_vFeatures, DWORD a_nACTimeMS) { // bruker dll handle check ASSERT(m_pBrukerDllHandle); if (!m_pBrukerDllHandle) { // error, invalid m_pBrukerDllHandle LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures: invalid m_pBrukerDllHandle.")); return FALSE; } // 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; // added by Jieshi 23/08/2017 WORD* pixelTimes(new WORD[nCollectCount]); BrukerFeature* features(new BrukerFeature[nCollectCount]); std::vector extraSegments; for (size_t i = 0; i < nCollectCount; i++) { BrukerFeature ofeature = a_vFeatures[i]; features[i].SegmentCount = ofeature.SegmentCount; if (ofeature.SegmentCount > 0) { features[i].pSegment = ofeature.pSegment; // calculate pixel time int nPixelCount = 0; for (int j = 0; j < ofeature.SegmentCount; j++) { nPixelCount += ofeature.pSegment[j].XCount; } pixelTimes[i] = (WORD)(ceil((double)a_nACTimeMS * 1000.0 / (double)nPixelCount)); nTotalPixelCount += nPixelCount; } else { // will generate according to the x-ray position // this shouldn't happen BrukerFeature* features(new BrukerFeature[nCollectCount]); extraSegments.push_back(BrukerSegment()); 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].pSegment = &extraSegments[extraSegments.size() - 1]; pixelTimes[i] = (WORD)(a_nACTimeMS * 1000); } } // ask bruker to collect a set of x-ray data if (!StartFeatureListMeasurement(nCollectCount, features, pixelTimes)) { // failed to call StartFeatureListMeasurement method LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::CollectXRayPointsByFeatures: failed to call StartFeatureListMeasurement method.")); 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(CPosXraysList& 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]; memset(cResult, 0, 10000); if (!m_pBrukerDllHandle->QuantifyFeatureListSpectrum(m_nClientID, i, pcMethod, pcParams, cResult, 10000, (RTSpectrumHeaderRec*)m_psRTSpectrumBuffer.get(), (int)BRUKER_PARAM::RT_SPECTRUM_BUFFER_SIZE)) { LogErrorTrace(__FILE__, __LINE__, _T("COTSBrukerImpl::SetXRayPoints failed to call QuantifyPointListSpectrum method, error code %d"), m_pBrukerDllHandle->GetLastReturn()); //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) { /*COTSXmlFileDllExportPtr lpXMLDllExport = COTSXmlFileDllExportPtr(new COTSXmlFileDllExport); return lpXMLDllExport->GetBrukerDLLVersion(DllXMLFileName,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; } }