|
@@ -0,0 +1,280 @@
|
|
|
+#pragma once
|
|
|
+#include "stdafx.h"
|
|
|
+#include "CFindPeaks.h"
|
|
|
+#include <algorithm>
|
|
|
+namespace CPeak
|
|
|
+{
|
|
|
+ const long ATOMIC_NUMBER_MIN = 1;
|
|
|
+ const long ATOMIC_NUMBER_MAX = 103;
|
|
|
+ const CString theElementNameList{ _T("H,He")
|
|
|
+ _T(",Li,Be,B,C,N,O,F,Ne")
|
|
|
+ _T(",Na,Mg,Al,Si,P,S,Cl,Ar")
|
|
|
+ _T(",K,Ca,Sc,Ti,V,Cr,Mn,Fe,Co,Ni,Cu,Zn,Ga,Ge,As,Se,Br,Kr")
|
|
|
+ _T(",Rb,Sr,Y,Zr,Nb,Mo,Tc,Ru,Rh,Pd,Ag,Cd,In,Sn,Sb,Te,I,Xe")
|
|
|
+ _T(",Cs,Ba,La")
|
|
|
+ _T(",Ce,Pr,Nd,Pm,Sm,Eu,Gd,Tb,Dy,Ho,Er,Tm,Yb,Lu")
|
|
|
+ _T(",Hf,Ta,W,Re,Os,Ir,Pt,Au,Hg,Tl,Pb,Bi,Po,At,Rn")
|
|
|
+ _T(",Fr,Ra,Ac")
|
|
|
+ _T(",Th,Pa,U,Np,Pu,Am,Cm,Bk,Cf,Es,Fm,Md,No,Lr") };
|
|
|
+ const CString ELEMENT_NAMES[ATOMIC_NUMBER_MAX] =
|
|
|
+ { _T("H"),_T("He"),
|
|
|
+ _T("Li"),_T("Be"),_T("B"),_T("C"),_T("N"),_T("O"),_T("F"),_T("Ne"),
|
|
|
+ _T("Na"),_T("Mg"),_T("Al"),_T("Si"),_T("P"),_T("S"),_T("Cl"),_T("Ar"),
|
|
|
+ _T("K"),_T("Ca"),_T("Sc"),_T("Ti"),_T("V"),_T("Cr"),_T("Mn"),_T("Fe"),_T("Co"),_T("Ni"),_T("Cu"),_T("Zn"),_T("Ga"),_T("Ge"),_T("As"),_T("Se"),_T("Br"),_T("Kr"),
|
|
|
+ _T("Rb"),_T("Sr"),_T("Y"),_T("Zr"),_T("Nb"),_T("Mo"),_T("Tc"),_T("Ru"),_T("Rh"),_T("Pd"),_T("Ag"),_T("Cd"),_T("In"),_T("Sn"),_T("Sb"),_T("Te"),_T("I"),_T("Xe"),
|
|
|
+ _T("Cs"),_T("Ba"),_T("La"),
|
|
|
+ _T("Ce"),_T("Pr"),_T("Nd"),_T("Pm"),_T("Sm"),_T("Eu"),_T("Gd"),_T("Tb"),_T("Dy"),_T("Ho"),_T("Er"),_T("Tm"),_T("Yb"),_T("Lu"),
|
|
|
+ _T("Hf"),_T("Ta"),_T("W"),_T("Re"),_T("Os"),_T("Ir"),_T("Pt"),_T("Au"),_T("Hg"),_T("Tl"),_T("Pb"),_T("Bi"),_T("Po"),_T("At"),_T("Rn"),
|
|
|
+ _T("Fr"),_T("Ra"),_T("Ac"),
|
|
|
+ _T("Th"),_T("Pa"),_T("U"),_T("Np"),_T("Pu"),_T("Am"),_T("Cm"),_T("Bk"),_T("Cf"),_T("Es"),_T("Fm"),_T("Md"),_T("No"),_T("Lr"),
|
|
|
+ };
|
|
|
+
|
|
|
+ const double ELEMENT_ATOMIC_WEIGHT_VALUES[ATOMIC_NUMBER_MAX] =
|
|
|
+ {
|
|
|
+ 1.008,4.003,
|
|
|
+ 6.941,9.012,10.811,12.011,14.007,15.999,18.998,20.180,
|
|
|
+ 22.990,24.305,26.982,28.086,30.974,32.066,35.453,39.948,
|
|
|
+ 39.098,40.08,44.956,47.88,50.942,51.996,54.938,55.847,58.933,58.70,63.546,65.39,69.72,72.61,74.922,78.96,79.904,83.80,
|
|
|
+ 85.468,87.62,88.906,91.22,92.906,95.94,98.00,101.07,102.906,106.42,107.868,112.41,114.82,118.71,121.76,127.60,126.905,131.29,
|
|
|
+ 132.905,137.33,138.906,
|
|
|
+ 140.12,140.908,144.24,145.0,150.36,151.97,157.25,158.925,162.50,64.93,167.26,168.934,173.04,174.967,
|
|
|
+ 178.49,180.948,183.85,186.207,190.20,192.22,195.08,196.967,200.59,204.38,207.2,208.980,209.00,210.00,222.00,
|
|
|
+ 223.00,226.025,227.028,
|
|
|
+ 232.038,231.036,238.029,237.048,244.00,243.00,247.00,247.00,251.00,252.00,257.00,258.00,259.00,260.00
|
|
|
+ };
|
|
|
+
|
|
|
+ const double ELEMENT_ENERGY_VALUES_K[ATOMIC_NUMBER_MAX] =
|
|
|
+ {
|
|
|
+ 0.0,0.0,
|
|
|
+ 0.0,0.108,0.185,0.277,0.392,0.523,0.677,0.848,
|
|
|
+ 1.040,1.254,1.486,1.740,2.013,2.307,2.622,2.957,
|
|
|
+ 2.313,3.691,4.090,4.510,4.952,5.414,5.898,6.403,6.929,7.477,8.040,8.637,9.250,9.885,10.542,11.220,11.922,12.649,
|
|
|
+ 13.393,14.163,14.955,15.776,16.617,17.481,18.368,19.282,20.217,21.180,22.166,23.175,24.209,25.272,26.359,27.471,28.615,29.779,
|
|
|
+ 30.971,32.196,33.441,
|
|
|
+ 34.717,36.031,37.358,38.725,40.118,41.534,42.992,44.476,45.997,47.534,49.100,50.730,52.362,54.078,
|
|
|
+ 55.801,57.450,59.305,61.122,62.989,64.906,66.834,68.804,70.806,72.769,74.989,77.091,79.272,81.513,83.771,
|
|
|
+ 86.098,88.480,90.880,
|
|
|
+ 93.382,95.886,98.434,100.800,103.320,105.970,109.737,111.676,114.776,0.0,0.0,0.0,0.0,0.0
|
|
|
+ };
|
|
|
+
|
|
|
+ const double ELEMENT_ENERGY_VALUES_L[ATOMIC_NUMBER_MAX] =
|
|
|
+ {
|
|
|
+ 0.0,0.0,
|
|
|
+ 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
|
|
|
+ 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
|
|
|
+ 0.0,0.341,0.395,0.452,0.511,0.573,0.637,0.705,0.776,0.851,0.930,1.012,1.098,1.188,1.282,1.379,1.480,1.586,
|
|
|
+ 1.694,1.806,1.922,2.042,2.166,2.293,2.424,2.558,2.696,2.838,2.984,3.133,3.286,3.443,3.604,3.768,3.937,4.109,
|
|
|
+ 4.286,4.465,4.650,
|
|
|
+ 4.839,5.033,5.229,5.432,5.636,5.845,6.056,6.272,6.494,6.719,6.947,7.179,7.414,7.654,
|
|
|
+ 7.898,8.145,8.396,8.651,8.910,9.174,9.441,9.712,9.987,10.256,10.550,10.837,11.129,11.425,11.725,
|
|
|
+ 12.029,12.338,12.650,
|
|
|
+ 12.967,13.288,13.612,13.941,14.275,14.615,14.961,15.309,15.661,16.018,0.0,0.0,0.0,0.0
|
|
|
+ };
|
|
|
+
|
|
|
+ const double ELEMENT_ENERGY_VALUES_M[ATOMIC_NUMBER_MAX] =
|
|
|
+ {
|
|
|
+ 0.0,0.0,
|
|
|
+ 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
|
|
|
+ 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
|
|
|
+ 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
|
|
|
+ 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
|
|
|
+ 0.0,0.779,0.833,
|
|
|
+ 0.883,0.929,0.978,1.032,1.081,1.137,1.185,1.240,1.293,1.347,1.405,1.462,1.521,1.581,
|
|
|
+ 1.644,1.709,1.774,1.842,1.910,1.978,2.048,2.120,2.191,2.268,2.342,2.419,2.505,2.585,2.665,
|
|
|
+ 2.747,2.830,2.915,
|
|
|
+ 2.991,3.077,3.165,3.253,3.344,3.435,3.539,3.634,3.731,3.829,0.0,0.0,0.0,0.0
|
|
|
+ };
|
|
|
+ const double ENERGY_VALUE_INVALID = -1.0;
|
|
|
+ const long GENERALXRAYCHANNELS = 2000;
|
|
|
+
|
|
|
+ double GetEnergyValueK(long a_nAtomNum)
|
|
|
+ {
|
|
|
+ double dEnergyValueK = ENERGY_VALUE_INVALID;
|
|
|
+ if (a_nAtomNum < 0 || a_nAtomNum >= ATOMIC_NUMBER_MAX)
|
|
|
+ {
|
|
|
+ return dEnergyValueK;
|
|
|
+ }
|
|
|
+ dEnergyValueK = ELEMENT_ENERGY_VALUES_K[a_nAtomNum - 1];
|
|
|
+ return dEnergyValueK;
|
|
|
+ }
|
|
|
+ double GetEnergyValueL(long a_nAtomNum)
|
|
|
+ {
|
|
|
+ double dEnergyValueL = ENERGY_VALUE_INVALID;
|
|
|
+ if (a_nAtomNum < 0 || a_nAtomNum >= ATOMIC_NUMBER_MAX)
|
|
|
+ {
|
|
|
+ return dEnergyValueL;
|
|
|
+ }
|
|
|
+ dEnergyValueL = ELEMENT_ENERGY_VALUES_L[a_nAtomNum - 1];
|
|
|
+ return dEnergyValueL;
|
|
|
+ }
|
|
|
+ double GetEnergyValueM(long a_nAtomNum)
|
|
|
+ {
|
|
|
+ double dEnergyValueM = ENERGY_VALUE_INVALID;
|
|
|
+ if (a_nAtomNum < 0 || a_nAtomNum >= ATOMIC_NUMBER_MAX)
|
|
|
+ {
|
|
|
+ return dEnergyValueM;
|
|
|
+ }
|
|
|
+ dEnergyValueM = ELEMENT_ENERGY_VALUES_M[a_nAtomNum - 1];
|
|
|
+ return dEnergyValueM;
|
|
|
+ }
|
|
|
+ std::vector<double>GetEnergyValues(long a_nAtomNum)
|
|
|
+ {
|
|
|
+ std::vector<double> vEnergyValues;
|
|
|
+ if (a_nAtomNum < 0 || a_nAtomNum >= ATOMIC_NUMBER_MAX)
|
|
|
+ {
|
|
|
+ return vEnergyValues;
|
|
|
+ }
|
|
|
+ double dEnergyValue = ELEMENT_ENERGY_VALUES_K[a_nAtomNum - 1];
|
|
|
+ vEnergyValues.push_back(dEnergyValue);
|
|
|
+ dEnergyValue = ELEMENT_ENERGY_VALUES_L[a_nAtomNum - 1];
|
|
|
+ vEnergyValues.push_back(dEnergyValue);
|
|
|
+ dEnergyValue = ELEMENT_ENERGY_VALUES_M[a_nAtomNum - 1];
|
|
|
+ vEnergyValues.push_back(dEnergyValue);
|
|
|
+ return vEnergyValues;
|
|
|
+ }
|
|
|
+ bool IsValidAtomNum(long a_nAtomNum)
|
|
|
+ {
|
|
|
+ return a_nAtomNum >= ATOMIC_NUMBER_MIN && a_nAtomNum <= ATOMIC_NUMBER_MAX;
|
|
|
+ }
|
|
|
+ void GetAllElementsEnergyK(float fEnergy, float fDelt, std::vector<CString>& vecstr)
|
|
|
+ {
|
|
|
+ float fResult = 0;
|
|
|
+ CString str = _T("");
|
|
|
+ vecstr.clear();
|
|
|
+
|
|
|
+ fDelt = (fDelt < 0) ? -fDelt : fDelt;
|
|
|
+
|
|
|
+ for (int i = 0; i < ATOMIC_NUMBER_MAX; i++)
|
|
|
+ {
|
|
|
+ fResult = (float)ELEMENT_ENERGY_VALUES_K[i] - fEnergy;
|
|
|
+ str = _T("");
|
|
|
+
|
|
|
+ // 左侧
|
|
|
+ if (fResult >= -fDelt && fResult < 0)
|
|
|
+ {
|
|
|
+ str.Format(_T("%.3f: %s"), fResult, ELEMENT_NAMES[i]);
|
|
|
+ vecstr.push_back(str);
|
|
|
+ }
|
|
|
+ // 右侧
|
|
|
+ else if (fResult <= fDelt && fResult >= 0)
|
|
|
+ {
|
|
|
+ str.Format(_T("+%.3f: %s"), fResult, ELEMENT_NAMES[i]);
|
|
|
+ vecstr.push_back(str);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ void SplitCString(const CString& str, const char* separator, int sep_number, vector<CString>& strArray)
|
|
|
+ {
|
|
|
+ strArray.clear();
|
|
|
+ int index = -1;
|
|
|
+ const int MAX_COUNT = 1000000; //最大分割长度
|
|
|
+ int smallIndex = MAX_COUNT;
|
|
|
+ CString szLeft;
|
|
|
+ CString szRight = str;
|
|
|
+
|
|
|
+ for (int i = 0; i < sep_number; i++)
|
|
|
+ {
|
|
|
+ index = szRight.Find(separator[i]);
|
|
|
+ if (index >= 0 && index < smallIndex)
|
|
|
+ {
|
|
|
+ smallIndex = index; //遍历获得所有的分割符的最小Index
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i == sep_number - 1 && smallIndex != MAX_COUNT) //遍历全部分割符之后
|
|
|
+ {
|
|
|
+ szLeft = szRight.Left(smallIndex);
|
|
|
+ szLeft.Trim(); //去除空格
|
|
|
+ if (!szLeft.IsEmpty()) strArray.push_back(szLeft);
|
|
|
+
|
|
|
+ szRight = szRight.Right(szRight.GetLength() - smallIndex - 1);
|
|
|
+ szRight.Trim();
|
|
|
+ if (szRight.GetLength() > 0)
|
|
|
+ {
|
|
|
+ i = -1;
|
|
|
+ smallIndex = MAX_COUNT;
|
|
|
+ }
|
|
|
+ else break;
|
|
|
+ }
|
|
|
+ else if (i == sep_number - 1)
|
|
|
+ {
|
|
|
+ szRight.Trim();
|
|
|
+ if (!szRight.IsEmpty()) strArray.push_back(szRight);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*return strArray.size();*/
|
|
|
+ }
|
|
|
+
|
|
|
+ bool cmp(const pair<int, int>& x, const pair<int, int>& y)
|
|
|
+ {
|
|
|
+ return x.second > y.second;
|
|
|
+ }
|
|
|
+
|
|
|
+ void SortMapByValue( map<int,int>& tMap, vector<pair<int, int>>& tVector)
|
|
|
+ {
|
|
|
+ for (map<int, int>::iterator curr = tMap.begin(); curr != tMap.end(); curr++)
|
|
|
+ tVector.push_back(make_pair(curr->first, curr->second));
|
|
|
+
|
|
|
+ std::sort(tVector.begin(), tVector.end(), cmp);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ BOOL FindPeaks(DWORD* nChannelData, vector<CString>& eleList)
|
|
|
+ {
|
|
|
+ //获取Peaks
|
|
|
+ DWORD m_nXrayData[GENERALXRAYCHANNELS];
|
|
|
+ memcpy(m_nXrayData, nChannelData, sizeof(DWORD) * GENERALXRAYCHANNELS);
|
|
|
+ map<int, int> tMap;
|
|
|
+ int countMap = 0;
|
|
|
+ for (size_t i = 0; i < GENERALXRAYCHANNELS; i++)
|
|
|
+ {
|
|
|
+ tMap.insert(pair<int, int>(i, m_nXrayData[i]));
|
|
|
+ countMap += m_nXrayData[i];
|
|
|
+ }
|
|
|
+ vector<pair<int, int>> tVector;
|
|
|
+ SortMapByValue(tMap, tVector);
|
|
|
+ vector<CString> nameList;
|
|
|
+ for (size_t i = 0; i < GENERALXRAYCHANNELS; i++)
|
|
|
+ {
|
|
|
+ if (tVector[i].second > countMap * 0.002)
|
|
|
+ {
|
|
|
+ std::vector<CString> vecstr;
|
|
|
+ GetAllElementsEnergyK((float)tVector[i].first / 100, 0.1f, vecstr);
|
|
|
+ if (vecstr.size() != 0)
|
|
|
+ {
|
|
|
+ LogErrorTrace(__FILE__, __LINE__, _T((vecstr[0])));
|
|
|
+ std::vector<CString> vecstrSplit;
|
|
|
+ SplitCString(vecstr[0], ":", 2, vecstrSplit);
|
|
|
+ if (std::find(nameList.begin(), nameList.end(), vecstrSplit[1]) == nameList.end())
|
|
|
+ {
|
|
|
+ nameList.push_back(vecstrSplit[1]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //判断Peaks是否存在
|
|
|
+ for each (CString var in nameList)
|
|
|
+ {
|
|
|
+ if (std::find(eleList.begin(), eleList.end(), var) == eleList.end())
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|