diff --git a/DbTables/inc/CalCosmicEnergyCalibInfo.hh b/DbTables/inc/CalCosmicEnergyCalibInfo.hh index 2df1741a6b..6dad9c88aa 100644 --- a/DbTables/inc/CalCosmicEnergyCalibInfo.hh +++ b/DbTables/inc/CalCosmicEnergyCalibInfo.hh @@ -6,6 +6,7 @@ #include #include #include +#include namespace mu2e { @@ -17,9 +18,9 @@ class CalCosmicEnergyCalibInfo : public DbTable { _cID(cID), _FirstCalibRun(FirstCalibRun), _LastCalibRun(LastCalibRun), - _EnergyMethod(EnergyMethod), - _FitMethod(FitMethod), - _Comment(Comment) {} + _EnergyMethod(std::move(EnergyMethod)), + _FitMethod(std::move(FitMethod)), + _Comment(std::move(Comment)) {} int cID() const {return _cID; } int FirstCalibRun() const { return _FirstCalibRun; } int LastCalibRun() const { return _LastCalibRun; } diff --git a/DbTables/inc/CalEnergyCalibInfo.hh b/DbTables/inc/CalEnergyCalibInfo.hh new file mode 100755 index 0000000000..d35625d62e --- /dev/null +++ b/DbTables/inc/CalEnergyCalibInfo.hh @@ -0,0 +1,147 @@ +#ifndef DbTables_CalEnergyCalibInfo_hh +#define DbTables_CalEnergyCalibInfo_hh + +/* + Per-SiPM combined calibration metadata table. + Stores the combined ADC/MeV constants, uncertainties, and status flags + from the cosmic + source calibration combination algorithm. + + Status codes: + 0 - updated: cosmic + source, consistent + 1 - fallback: methods inconsistent, kept old value + 2 - fallback: all methods statistically invalid + 101 - updated using cosmic only + 102 - updated using source only + + Author: W. Zhou 2025 +*/ + +#include +#include +#include +#include +#include +#include "cetlib_except/exception.h" +#include "Offline/DbTables/inc/DbTable.hh" +#include "Offline/DataProducts/inc/CaloSiPMId.hh" +#include "Offline/DataProducts/inc/CaloConst.hh" + +namespace mu2e { + +class CalEnergyCalibInfo : public DbTable { + public: + typedef std::shared_ptr ptr_t; + typedef std::shared_ptr cptr_t; + + class Row { + public: + Row(CaloSiPMId roid, float ADC2MeV, float ADC2MeV_err, + int status_code, std::string status_message) + : _roid(roid), + _ADC2MeV(ADC2MeV), + _ADC2MeV_err(ADC2MeV_err), + _status_code(status_code), + _status_message(std::move(status_message)) {} + + CaloSiPMId roid() const { return _roid; } + float ADC2MeV() const { return _ADC2MeV; } + float ADC2MeV_err() const { return _ADC2MeV_err; } + int status_code() const { return _status_code; } + std::string status_message() const { return _status_message; } + + private: + CaloSiPMId _roid; + float _ADC2MeV; + float _ADC2MeV_err; + int _status_code; + std::string _status_message; + }; + + constexpr static const char* cxname = "CalEnergyCalibInfo"; + + CalEnergyCalibInfo() + : DbTable(cxname, "cal.energycalibinfo", + "roid,adc2mev,adc2mev_err,status_code,status_message") {} + + const Row& row(CaloSiPMId roid) const { return _rows.at(roid.id()); } + std::vector const& rows() const { return _rows; } + std::size_t nrow() const override { return _rows.size(); } + size_t size() const override { return baseSize() + nrow() * sizeof(Row); } + tableType type() const override { return Adhoc; } + virtual std::size_t nrowFix() const override { return CaloConst::_nChannelDB; } + const std::string orderBy() const { return std::string("roid"); } + + void addRow(const std::vector& columns) override { + std::uint16_t index = std::stoul(columns[0]); + // enforce order, so channels can be looked up by index + if (index >= CaloConst::_nChannelDB || index != _rows.size()) { + throw cet::exception("CALENERGYCALIBINFO_BAD_INDEX") + << "CalEnergyCalibInfo::addRow found index out of order: " << index + << " != " << _rows.size() << "\n"; + } + std::string statusMessage = columns[4]; + for (std::size_t i = 5; i < columns.size(); ++i) { + statusMessage += ","; + statusMessage += columns[i]; + } + + _rows.emplace_back(CaloSiPMId(index), std::stof(columns[1]), + std::stof(columns[2]), std::stoi(columns[3]), + fromCsvText(statusMessage)); + } + + void rowToCsv(std::ostringstream& sstream, std::size_t irow) const override { + Row const& r = _rows.at(irow); + sstream << r.roid() << ","; + sstream << std::fixed << std::setprecision(5); + sstream << r.ADC2MeV() << ","; + sstream << r.ADC2MeV_err() << ","; + sstream << r.status_code() << ","; + sstream << toCsvText(r.status_message()); + } + + virtual void clear() override { + baseClear(); + _rows.clear(); + } + + private: + static std::string toCsvText(const std::string& text) { + if (text.find_first_of(",\"") == std::string::npos) return text; + std::string out; + out.reserve(text.size() + 2); + out.push_back('"'); + for (char c : text) { + if (c == '"') out += "\"\""; + else out.push_back(c); + } + out.push_back('"'); + return out; + } + + static std::string fromCsvText(const std::string& text) { + if (text.size() < 2 || text.front() != '"' || text.back() != '"') { + return text; + } + std::string out; + out.reserve(text.size() - 2); + for (std::size_t i = 1; i + 1 < text.size(); ++i) { + if (text[i] == '"' && i + 2 < text.size() && text[i + 1] == '"') { + out.push_back('"'); + ++i; + } else if (text[i] == '\\' && i + 2 < text.size() && text[i + 1] == '"') { + out.push_back('"'); + ++i; + } else { + out.push_back(text[i]); + } + } + return out; + } + + std::vector _rows; +}; + +} // namespace mu2e + +#endif diff --git a/DbTables/inc/CalSourceEnergyCalib.hh b/DbTables/inc/CalSourceEnergyCalib.hh index 89211d298f..92e940a545 100644 --- a/DbTables/inc/CalSourceEnergyCalib.hh +++ b/DbTables/inc/CalSourceEnergyCalib.hh @@ -16,7 +16,7 @@ namespace mu2e { class Row { public: - Row(CaloSiPMId roid, float fullEPeak,float fullErrEPeak,float fullWidth,float fullErrWidth,float firstescEPeak,float firstescErrEPeak,float firstescWidth,float firstescErrWidth,float secescEPeak,float secescErrEPeak,float secescWidth,float secescErrWidth, float frFull, float frFirst, float frSecond, float chisq): _roid(roid), _fullEPeak(fullEPeak), _fullErrEPeak(fullErrEPeak), _fullWidth(fullWidth), _fullErrWidth(fullErrWidth),_firstescEPeak(firstescEPeak), _firstescErrEPeak(firstescErrEPeak), _firstescWidth(firstescWidth), _firstescErrWidth(firstescErrWidth),_secescEPeak(secescEPeak), _secescErrEPeak(secescErrEPeak), _secescWidth(secescWidth), _secescErrWidth(secescErrWidth), _frFull(frFull), _frFirst(frFirst), _frSecond(frSecond), _chisq(chisq){} + Row(CaloSiPMId roid, float fullEPeak,float fullErrEPeak,float fullWidth,float fullErrWidth,float firstescEPeak,float firstescErrEPeak,float firstescWidth,float firstescErrWidth,float secescEPeak,float secescErrEPeak,float secescWidth,float secescErrWidth, float frFull, float frFirst, float frSecond, float chisq, int ndf): _roid(roid), _fullEPeak(fullEPeak), _fullErrEPeak(fullErrEPeak), _fullWidth(fullWidth), _fullErrWidth(fullErrWidth),_firstescEPeak(firstescEPeak), _firstescErrEPeak(firstescErrEPeak), _firstescWidth(firstescWidth), _firstescErrWidth(firstescErrWidth),_secescEPeak(secescEPeak), _secescErrEPeak(secescErrEPeak), _secescWidth(secescWidth), _secescErrWidth(secescErrWidth), _frFull(frFull), _frFirst(frFirst), _frSecond(frSecond), _chisq(chisq), _ndf(ndf){} CaloSiPMId roid() const { return _roid;} float fullEPeak() const { return _fullEPeak; } @@ -39,6 +39,7 @@ namespace mu2e { float frSecond() const { return _frSecond; } float chisq() const { return _chisq; } + int ndf() const { return _ndf; } private: CaloSiPMId _roid; @@ -58,11 +59,12 @@ namespace mu2e { float _frFirst; float _frSecond; float _chisq; + int _ndf; }; constexpr static const char* cxname = "CalSourceEnergyCalib"; - CalSourceEnergyCalib():DbTable(cxname,"cal.sourceenergycalib","roid,fullepeak,fullerrepeak,fullwidth,fullerrwidth,firstescepeak,firstescerrepeak,firstescwidth,firstescerrwidth,secescepeak,secescerrepeak,secescwidth,secescerrwidth, frfull,frfirst,frsecond,chisq"){} + CalSourceEnergyCalib():DbTable(cxname,"cal.sourceenergycalib","roid,fullepeak,fullerrepeak,fullwidth,fullerrwidth,firstescepeak,firstescerrepeak,firstescwidth,firstescerrwidth,secescepeak,secescerrepeak,secescwidth,secescerrwidth,frfull,frfirst,frsecond,chisq,ndf"){} const Row& row(CaloSiPMId roid) const { return _rows.at(roid.id()); } @@ -82,7 +84,7 @@ namespace mu2e { _rows.emplace_back(CaloSiPMId(index),std::stof(columns[1]),std::stof(columns[2]),std::stof(columns[3]), std::stof(columns[4]),std::stof(columns[5]),std::stof(columns[6]),std::stof(columns[7]), std::stof(columns[8]),std::stof(columns[9]),std::stof(columns[10]),std::stof(columns[11]), - std::stof(columns[12]),std::stof(columns[13]),std::stof(columns[14]),std::stof(columns[15]),std::stof(columns[16])); + std::stof(columns[12]),std::stof(columns[13]),std::stof(columns[14]),std::stof(columns[15]),std::stof(columns[16]),std::stoi(columns[17])); } @@ -102,7 +104,11 @@ namespace mu2e { sstream << r.secescErrEPeak()<<","; sstream << r.secescWidth()<<","; sstream << r.secescErrWidth()<<","; - sstream << r.chisq(); + sstream << r.frFull()<<","; + sstream << r.frFirst()<<","; + sstream << r.frSecond()<<","; + sstream << r.chisq()<<","; + sstream << r.ndf(); } virtual void clear() override { baseClear(); _rows.clear();} diff --git a/DbTables/src/DbTableFactory.cc b/DbTables/src/DbTableFactory.cc index f49459c491..65a7193eb6 100644 --- a/DbTables/src/DbTableFactory.cc +++ b/DbTables/src/DbTableFactory.cc @@ -14,6 +14,7 @@ #include "Offline/DbTables/inc/CalSourceEnergyCalib.hh" #include "Offline/DbTables/inc/CalCosmicEnergyCalib.hh" #include "Offline/DbTables/inc/CalCosmicEnergyCalibInfo.hh" +#include "Offline/DbTables/inc/CalEnergyCalibInfo.hh" #include "Offline/DbTables/inc/CalLaserEnergyCalib.hh" #include "Offline/DbTables/inc/CalLaserTimeCalib.hh" #include "Offline/DbTables/inc/CalLaserRuns.hh" @@ -114,6 +115,8 @@ mu2e::DbTable::ptr_t mu2e::DbTableFactory::newTable(std::string const& name) { return std::shared_ptr(new mu2e::CalLaserRuns()); } else if (name=="CalEnergyCalib") { return std::shared_ptr(new mu2e::CalEnergyCalib()); + } else if (name=="CalEnergyCalibInfo") { + return std::shared_ptr(new mu2e::CalEnergyCalibInfo()); } else if (name=="CalTimeCalib") { return std::shared_ptr(new mu2e::CalTimeCalib()); } else if (name=="CalCosmicT0Align") {