#include "DataStore.h" #include #include #include #include #include #include #include #include #include #include "GammaAnalyAlgLib.h" #include "GammaAnalyALG.h" #include "analyseflow.h" #define double_to_no_precision(x) x,0,'f' #define double_to_six_precision(x) x,15,'f',6 #define DBL_MAX 1.7976931348623158e+308 //#define OPERATOR_Manager QLatin1String("管理员") //#define OPERATOR_Analyst QLatin1String("分析员") //#define OPERATOR_SeniorAnalyst QLatin1String("高级分析员") #define Role_Manager QString("Administrator") #define Role_SuperAnalyst QString("SeniorAnalyst") #define Role_Analyst QString("Analyst") #define SAMPLEID QLatin1String("ANLYSAMPLEID") #define OPERATOR_AUTO QLatin1String("Auto") #define DECLARESAMPLEID QLatin1String("SMAPLEID") #define ANLYID QLatin1String("ANLYID") #define Status_U QLatin1String("U") #define Status_R QLatin1String("R") #define Status_F QLatin1String("F") DataStore* DataStore::m_dataStore = 0; DataStore::DataStore() : m_phd(0), m_nCount(0), m_nSChan(0), m_dStep(0.25), m_bRewriteAll(false) { // 加载默认用户核素库 m_userlib_G = AlgFunc::UserNuclide("G"); m_userlib_P = AlgFunc::UserNuclide("P"); } DataStore *DataStore::GetDataStore() { if(m_dataStore == 0) { m_dataStore = new DataStore(); } return m_dataStore; } DataStore::~DataStore() { } bool DataStore::AnalyseData(QString strPath, ThrCallBack callFuc) { AnalyseFlow fow(this, strPath, callFuc); // printf("1######\n"); } void DataStore::SetQuery(const QSqlQuery &query, bool bRemote) { m_bFromDB = bRemote; m_query = query; m_mapNucLineG = GetNuclideLines(m_userlib_G); m_mapNucLineP = GetNuclideLines(m_userlib_P); } void DataStore::SetPHD(PHDFile* phd) { m_phd = phd; m_nCount = 0; m_vCount.clear(); m_userlib.clear(); if(m_phd) { m_nCount = phd->Spec.num_g_channel; m_nSChan = phd->Spec.begin_channel; // 确保绘制曲线时所有谱都是从1道开始 int i = 0; if(m_nSChan == 0) i = 1; for(; iSpec.counts[i]); } if(m_nSChan == 0) m_vCount.push_back(0); // 加载默认用户核素库 if(phd->header.system_type.toUpper() == "G") { if(m_userlib_G.isEmpty()) m_userlib_G = AlgFunc::UserNuclide("G"); m_userlib = m_userlib_G; } else { if(m_userlib_P.isEmpty()) m_userlib_P = AlgFunc::UserNuclide("P"); m_userlib = m_userlib_P; } } } int DataStore::GetChannelByEnergy(double energy, int startIndex) { // 注:索引从0开始,道从1开始,道 = 索引 + 1 if(startIndex < 0) startIndex = 0; int channel = startIndex + 1; // 将 channel 设为 startIndex 处的道数 for(int i=channel; ivEnergy.size(); ++i) // 从 startIndex 的下一个索引开始 { if(m_phd->vEnergy[i] >= energy) { if(m_phd->vEnergy[i] - energy > energy - m_phd->vEnergy[i-1]) channel = i; // 道在索引(i-1)处 else channel = i+1; // 道在索引(i)处 break; } } return channel; } double DataStore::GetEnergyByFloatChan(double x) { // 算法描述:取指定点附近的两点,根据 y=ax+b 方程求指定点处的能量 double y = 0.0; int channel = x; int index = channel > 0 ? channel-1 : channel; // 确保索引大于等于0 if(m_phd->vEnergy.size() == m_nCount && index < m_nCount) // 确保索引有效 { int index2 = (index < m_nCount-1 ? index + 1 : index - 1); double y1 = m_phd->vEnergy[index]; double y2 = m_phd->vEnergy[index2]; y = y1 + (y2 - y1) / (index2 - index) * (x - index); } return y; } int DataStore::FindNearPeak(const vector &vPeak, int channel, bool *bFind) { bool t_bFind = false; int i=0, peakNum = vPeak.size(); for(; i= peak.left && channel <= peak.right) // 如果 channel 在峰的左右边界内 { if(peak.multiIndex > 0 && channel > peak.peakCentroid) // 如果是重峰,且 channel 在重峰的第一个峰的中心道右侧 { int j = i; double temp = channel - peak.peakCentroid; while(++j < peakNum && vPeak[j].multiIndex == peak.multiIndex) { if(qAbs(vPeak[j].peakCentroid - channel) < temp) // 找出重峰中峰中心道离 channel 最近的峰 { temp = qAbs(vPeak[j].peakCentroid - channel); i = j; } } } // channel 在索引(i)对应的峰内 t_bFind = true; break; } else if(peak.left > channel) // channel 不在任何峰内,找离它最近的峰 { if(i>0 && channel-vPeak[i-1].peakCentroid < peak.peakCentroid-channel) i -= 1; break; } } if(i >= peakNum) i -= 1; if(bFind) *bFind = t_bFind; return i; } double DataStore::GetSignificance(int channel) { double signif = 0.0; bool bFind; int peakIndex = FindNearPeak(m_phd->vPeak, channel, &bFind); if(bFind) { signif = m_phd->vPeak[peakIndex].significance; } return signif; } double DataStore::GetSignificance(double energy) { return GetSignificance(GetChannelByEnergy(energy)); } /*ChartData DataStore::Energy_Count(double start, double end) { ChartData cData; if(start < end) { int startIndex = GetChannelByEnergy(start); int endIndex = GetChannelByEnergy(end, startIndex); cData = Energy_Count(startIndex, endIndex); } return cData; }*/ QString RightFill(QString str, int fieldWidth = 0, QChar fillChar = ' ') { int fillNum = fieldWidth - str.length(); while(fillNum > 0) { str.append(fillChar); --fillNum; } return str; } QString DataStore::MakeUpSpectrum(PHDFile *phd) { QString spectrum = ""; spectrum += "BEGIN IMS2.0" + STRING_END; spectrum += QString("MSG_TYPE %1%2").arg(phd->msgInfo.msg_type, STRING_END); spectrum += QString("MSG_ID %1 %2%3").arg(phd->msgInfo.msg_id, phd->msgInfo.msg_src_code, STRING_END); if(phd->msgInfo.verify_srid) { spectrum += "REF_ID" + STRING_END; spectrum += QString("%1 %2 %3 %4%5").arg(phd->msgInfo.ref_id_str, phd->msgInfo.ref_src_code, phd->msgInfo.seq_num, phd->msgInfo.tot_num, STRING_END); spectrum += QString("PROD_ID %1 %2%3").arg(phd->msgInfo.product_id, phd->msgInfo.delivery_id, STRING_END); } spectrum += QString("DATA_TYPE %1%2").arg(phd->msgInfo.data_type, STRING_END); QStringList data_types; data_types.push_back("SAMPLEPHD"); data_types.push_back("SPHDF"); data_types.push_back("SPHDP"); data_types.push_back("GASBKPHD"); data_types.push_back("BLANKPHD"); data_types.push_back("DETBKPHD"); data_types.push_back("QCPHD"); data_types.push_back("CALIBPHD"); if(!data_types.contains(phd->msgInfo.data_type)) return spectrum; // #Header spectrum += QString("#Header %1%2").arg(phd->header.designator, STRING_END); spectrum += QString("%1 %2 %3 %4 %5%6").arg(RightFill(phd->header.site_code, 5), RightFill(phd->header.detector_code, 9), RightFill(phd->header.system_type, 1), RightFill(phd->header.sample_geometry, 17), RightFill(phd->header.spectrum_quantity, 4), STRING_END); spectrum += phd->header.sample_ref_id + STRING_END; spectrum += QString("%1 %2 %3%4").arg(RightFill(phd->header.measurement_id, 31), RightFill(phd->header.detector_bk_measurement_id, 31), phd->header.gas_bk_measurement_id, STRING_END); spectrum += QString("%1 %2%3").arg(phd->header.transmit_date, phd->header.transmit_time, STRING_END); // #Comment if(!phd->oriTotalCmt.isEmpty()) { QString comment = phd->oriTotalCmt.replace("\r\n", "\n"); comment.replace("\n", STRING_END); spectrum += "#Comment" + STRING_END; spectrum += comment + STRING_END; } // #Collection spectrum += "#Collection" + STRING_END; spectrum += QString("%1 %2 %3 %4 %5%6").arg(phd->collect.collection_start_date, phd->collect.collection_start_time, phd->collect.collection_stop_date, phd->collect.collection_stop_time, QString::number(phd->collect.air_volume), STRING_END); // #Acquisition spectrum += "#Acquisition" + STRING_END; spectrum += QString("%1 %2 %3 %4").arg(phd->acq.acquisition_start_date) .arg(phd->acq.acquisition_start_time) .arg(RightFill(QString::number(phd->acq.acquisition_real_time, 'f', 2), 14)) .arg(RightFill(QString::number(phd->acq.acquisition_live_time, 'f', 2), 14)) + STRING_END; // #Processing if(phd->process.sample_volume_of_Xe > 0) { spectrum += "#Processing" + STRING_END; spectrum += QString("%1 %2%3 %4 %5%6 %7%8").arg(RightFill(QString::number(phd->process.sample_volume_of_Xe), 8), RightFill(QString::number(phd->process.uncertainty_1), 8), STRING_END, RightFill(QString::number(phd->process.Xe_collection_yield), 8), RightFill(QString::number(phd->process.uncertainty_2), 8), STRING_END, phd->process.archive_bottle_id, STRING_END); } // #Sample if(phd->sampleBlock.dimension_1 > 0) { spectrum += "#Sample" + STRING_END; spectrum += QString("%1 %2").arg(phd->sampleBlock.dimension_1).arg(phd->sampleBlock.dimension_2) + STRING_END; } // Certificate if(!phd->certificate.g_energy.isEmpty()) { spectrum += "#Certificate" + STRING_END; spectrum += phd->certificate.total_source_activity + phd->certificate.assay_date + phd->certificate.assay_time + phd->certificate.units_activity + STRING_END; int fieldWidth = 12; for(int i=0; icertificate.g_energy.size(); ++i) { spectrum += QString("%1 %2 %3 %4 %5 %6 %7 %8 %9") .arg(phd->certificate.nuclide_name[i], fieldWidth) .arg(phd->certificate.half_life_time[i], fieldWidth) .arg(phd->certificate.time_unit[i], fieldWidth) .arg(phd->certificate.activity_nuclide_time_assay[i], fieldWidth) .arg(phd->certificate.uncertainty[i], fieldWidth) .arg(phd->certificate.g_energy[i], fieldWidth) .arg(phd->certificate.g_intensity[i], fieldWidth) .arg(phd->certificate.electron_decay_mode[i], fieldWidth) .arg(phd->certificate.maximum_energy[i], fieldWidth) .arg(phd->certificate.intensity_b_particle[i], fieldWidth) + STRING_END; } } // #Calibration if(!phd->calibration.date_calibration.isEmpty()) { spectrum += "#Calibration" + STRING_END; spectrum += QString("%1 %2%3").arg(phd->calibration.date_calibration).arg(phd->calibration.time_calibration).arg(STRING_END); } // #g_Energy spectrum += "#g_Energy" + STRING_END; const G_EnergyBlock &g_ener = phd->usedEnerKD; for(int i=0; iusedResoKD; for(int i=0; iusedEffiKD; for(int i=0; iusedTotEKD.g_energy.size() > 0) { spectrum += "#TotalEff" + STRING_END; const TotaleffBlock &g_totE = phd->usedTotEKD; for(int i=0; iSpec.num_g_channel), 5), RightFill(QString::number(phd->Spec.g_energy_span), 4)) + STRING_END; int i=0, j=phd->Spec.begin_channel, len = phd->Spec.counts.length(); for(; iSpec.counts[i]), 10)) .arg(RightFill(QString::number(phd->Spec.counts[i+1]), 10)) .arg(RightFill(QString::number(phd->Spec.counts[i+2]), 10)) .arg(RightFill(QString::number(phd->Spec.counts[i+3]), 10)) .arg(RightFill(QString::number(phd->Spec.counts[i+4]), 10)).append(STRING_END); } if(i < len) { spectrum += QString("%1 %2").arg(RightFill(QString::number(j), 5)) .arg(RightFill(QString::number(phd->Spec.counts[i]), 10)); for(i = i+1; i < phd->Spec.num_g_channel; ++i) { spectrum += QString(" %1").arg(RightFill(QString::number(phd->Spec.counts[i]), 10)); } spectrum += STRING_END; } spectrum += "STOP" + STRING_END; return spectrum; } int DataStore::SettingChanged(PHDFile *phd) { SpecSetup &newSets = phd->setting; SpecSetup &oldSets = phd->usedSetting; if(newSets.ECutAnalysis_Low != oldSets.ECutAnalysis_Low || newSets.ECutAnalysis_High != oldSets.ECutAnalysis_High || newSets.EnergyTolerance != oldSets.EnergyTolerance || newSets.PSS_low != oldSets.PSS_low || newSets.BaseImprovePSS != oldSets.BaseImprovePSS || newSets.k_back != oldSets.k_back || newSets.k_alpha != oldSets.k_alpha || newSets.k_beta != oldSets.k_beta || newSets.RiskLevelK != oldSets.RiskLevelK || newSets.refTime_act != oldSets.refTime_act || newSets.refTime_conc != oldSets.refTime_conc) { return 1; } stdvec &old_ener = phd->usedEnerPara.p; stdvec &new_ener = phd->mapEnerPara[phd->newEner].p; if(old_ener.size() != new_ener.size()) return 1; for(int i=0; i 1E-6) return 1; } stdvec &old_reso = phd->usedResoPara.p; stdvec &new_reso = phd->mapResoPara[phd->newReso].p; if(old_reso.size() != new_reso.size()) return 1; for(int i=0; i 1E-6) return 1; } stdvec &old_effi = phd->usedEffiPara.p; stdvec &new_effi = phd->mapEffiPara[phd->newEffi].p; if(old_effi.size() != new_effi.size()) return -1; for(int i=0; i 1E-6) return -1; } return 0; } QVector DataStore::DetailedInfo() { // Sample_Id, Station_Code, Detector_Code, System_Type, Data_Type, Spectral_Qualifier, // SRID, Sample_Status, Collect_Start, Sampling_Time, Quantity, Flow_Rate, // Acq_Start, Acq_Real, Acq_Live, Decay_Time, Auto_Cat, Category QVector detailInfo(18, ""); detailInfo[0] = m_phd->id_sample; // Sample_Id detailInfo[1] = m_phd->header.site_code; // Station_Code detailInfo[2] = m_phd->header.detector_code; // Detector_Code detailInfo[3] = m_phd->header.system_type; // System_Type detailInfo[4] = m_phd->msgInfo.data_type; // Data_Type detailInfo[5] = m_phd->header.spectrum_quantity; // Spectral_Qualifier detailInfo[6] = m_phd->header.sample_ref_id; // SRID detailInfo[7] = m_phd->status; // Sample_Status QDateTime collect_stop_dt = QDateTime::fromString(m_phd->collect.collection_stop_date + " " + m_phd->collect.collection_stop_time, QString(DATATIME_FORMAT)); detailInfo[8] = m_phd->collect.collection_start_date + " " + m_phd->collect.collection_start_time; double timeSpan = QDateTime::fromString(detailInfo[8], QString(DATATIME_FORMAT)).secsTo(collect_stop_dt) / 3600.0; detailInfo[9] = QString::number(timeSpan, 'f', 2); // Sampling_Time detailInfo[10] = QString("%1").arg(m_phd->collect.air_volume, 0, 'f', 2); if(timeSpan != 0) detailInfo[11] = QString("%1").arg(m_phd->collect.air_volume / timeSpan, 0, 'f', 2); detailInfo[12] = m_phd->acq.acquisition_start_date + " " + m_phd->acq.acquisition_start_time; detailInfo[13] = QString("%1").arg(m_phd->acq.acquisition_real_time, 0, 'f', 2); detailInfo[14] = QString("%1").arg(m_phd->acq.acquisition_live_time, 0, 'f', 2); qint64 timespan = collect_stop_dt.secsTo(QDateTime::fromString(detailInfo[12], QString(DATATIME_FORMAT))); detailInfo[15] = QString::number(timespan / 3600.0, 'f', 2); detailInfo[17] = m_phd->category; return detailInfo; } QMap DataStore::GetNuclideLines(const QStringList nuclideList) { QMap mapLines; if(nuclideList.size() < 1) return mapLines; QString table_lines = m_bFromDB ? T_NUL_LINE_REMOTE : T_NUL_LINE_LOCAL; QString table_lib = m_bFromDB ? T_NUL_LIB_REMOTE : T_NUL_LIB_LOCAL; foreach (QString name, nuclideList) { NuclideLines nlines; QString sql = QString("select fullname, energy, energy_uncert, yield, yield_uncert, key_flag from %1 where name = '%2' Order by energy").arg(table_lines).arg(name); if(m_query.exec(sql)) { int j=0; while(m_query.next()) { nlines.fullNames.push_back(m_query.value(0).toString()); nlines.vEnergy.push_back(m_query.value(1).toDouble()); nlines.vUncertE.push_back(m_query.value(2).toDouble()); nlines.vYield.push_back(m_query.value(3).toDouble() / 100); nlines.vUncertY.push_back(m_query.value(4).toDouble()); if(m_query.value(5).toInt() > 0) { nlines.key_flag = j; nlines.maxYeildIdx = j; } ++j; } } mapLines[name] = nlines; } QString names = nuclideList.join("','"); names.insert(0, "'"); names.insert(names.length(), "'"); QString sql = QString("select name, halflife from %1 where name in (%2)").arg(table_lib).arg(names); if(m_query.exec(sql)) { while (m_query.next()) { mapLines[m_query.value(0).toString()].halflife = m_query.value(1).toDouble() * 86400; // 将天转换成秒 } } return mapLines; } QMap DataStore::GetNuclideLines() { QMap t_map; if(m_phd) { t_map = (m_phd->header.system_type == "P" ? m_mapNucLineP : m_mapNucLineG); } return t_map; } QString Str_DateTime(QString date, QString time) { if(date.size() != 10 || time.size() < 8) return QString(); else return date + " " + time.left(8); } QString DataStore::BaseCtrlToString(const BaseControls &baseCtrl) { QString strRet = ""; strRet += "#AnalyseRange" + LINE_END; strRet += QString("%1 %2").arg(baseCtrl.rg_low).arg(baseCtrl.rg_high) + LINE_END; int numPerLine = 5; size_t i, nCP = baseCtrl.XCtrl.size(), nGroupCP = nCP / numPerLine * numPerLine; strRet += "#XCtrl" + LINE_END; const stdvec &cx = baseCtrl.XCtrl; for(i=0; i