1919#include < vector>
2020#include < string>
2121#include < algorithm>
22+ #include < sstream>
2223
2324#include < fmt/format.h>
2425
3738#include " CCDB/CcdbObjectInfo.h"
3839#include " TPCBase/CDBInterface.h"
3940#include " TPCBase/CalDet.h"
41+ #include " TPCBase/CRUCalibHelpers.h"
4042#include " TPCWorkflow/CalibRawPartInfo.h"
4143#include " TPCWorkflow/CalDetMergerPublisherSpec.h"
4244#include " TPCWorkflow/ProcessingHelpers.h"
@@ -52,7 +54,7 @@ class CalDetMergerPublisherSpec : public o2::framework::Task
5254 using CcdbObjectInfo = o2::ccdb::CcdbObjectInfo;
5355
5456 public:
55- CalDetMergerPublisherSpec (uint32_t lanes, bool skipCCDB, bool dumpAfterComplete = false ) : mLanesToExpect (lanes), mCalibInfos (lanes), mSkipCCDB (skipCCDB), mPublishAfterComplete (dumpAfterComplete) {}
57+ CalDetMergerPublisherSpec (uint32_t lanes, bool skipCCDB, bool sendToDCS, bool dumpAfterComplete = false ) : mLanesToExpect (lanes), mCalibInfos (lanes), mSkipCCDB (skipCCDB), mSendToDCS (sendToDCS ), mPublishAfterComplete (dumpAfterComplete) {}
5658
5759 void init (o2::framework::InitContext& ic) final
5860 {
@@ -154,10 +156,12 @@ class CalDetMergerPublisherSpec : public o2::framework::Task
154156 CDBType mCalDetMapType ; // /< calibration type of CalDetMap object
155157 uint64_t mRunNumber {0 }; // /< processed run number
156158 uint32_t mLanesToExpect {0 }; // /< number of expected lanes sending data
159+ uint32_t mDCSSpecOffset {32768 }; // /< offset for DCS specs
157160 bool mForceQuit {false }; // /< for quit after processing finished
158161 bool mDirectFileDump {false }; // /< directly dump the calibration data to file
159162 bool mPublishAfterComplete {false }; // /< dump calibration directly after data from all lanes received
160163 bool mSkipCCDB {false }; // /< skip sending of calibration data
164+ bool mSendToDCS {false }; // /< skip sending of calibration data
161165 bool mCheckCalibInfos {false }; // /< check calib infos
162166
163167 // ____________________________________________________________________________
@@ -170,7 +174,6 @@ class CalDetMergerPublisherSpec : public o2::framework::Task
170174 }
171175
172176 // perhaps should be changed to time of the run
173- const auto now = std::chrono::system_clock::now ();
174177 const long timeStart = mCalibInfos [0 ].tfIDInfo .creation + mCalibInfos [0 ].publishCycle ;
175178 const long timeEnd = o2::ccdb::CcdbObjectInfo::INFINITE_TIMESTAMP;
176179
@@ -193,6 +196,11 @@ class CalDetMergerPublisherSpec : public o2::framework::Task
193196 o2::header::DataHeader::SubSpecificationType subSpec{(o2::header::DataHeader::SubSpecificationType)mCalDetMapType };
194197 output.snapshot (Output{clbUtils::gDataOriginCDBPayload , " TPC_CALIB" , subSpec}, *image.get ());
195198 output.snapshot (Output{clbUtils::gDataOriginCDBWrapper , " TPC_CALIB" , subSpec}, w);
199+
200+ // for pedestal calibration send to DCS if requested
201+ if (mSendToDCS && (mCalDetMapType == CDBType::CalPedestalNoise)) {
202+ sendPedestalNoiseToDCS (output);
203+ }
196204 }
197205
198206 for (auto & [type, object] : mMergedCalDets ) {
@@ -238,16 +246,74 @@ class CalDetMergerPublisherSpec : public o2::framework::Task
238246 }
239247 }
240248 }
249+
250+ void sendPedestalNoiseToDCS (DataAllocator& output)
251+ {
252+ auto sendObject = [this , &output](const CalPad& data, const std::string& path, const std::string& fileNameBase = " " ) {
253+ const long timeStart = mCalibInfos [0 ].tfIDInfo .creation + mCalibInfos [0 ].publishCycle ;
254+ const long timeEnd = o2::ccdb::CcdbObjectInfo::INFINITE_TIMESTAMP;
255+
256+ const auto dataMap = cru_calib_helpers::getDataMap (data);
257+ std::ostringstream dataStr;
258+ cru_calib_helpers::writeValues (dataStr, dataMap);
259+
260+ std::vector<char > dataVec;
261+ const auto & str = dataStr.str ();
262+ std::copy (str.begin (), str.end (), std::back_inserter (dataVec));
263+
264+ o2::ccdb::CcdbObjectInfo w;
265+
266+ w.setPath (path);
267+ w.setFileName (fmt::format (" {}_{}_{}.txt" , fileNameBase, mRunNumber , timeStart));
268+ w.setStartValidityTimestamp (timeStart);
269+ w.setEndValidityTimestamp (timeEnd);
270+
271+ auto md = w.getMetaData ();
272+ md[o2::base::NameConf::CCDBRunTag.data ()] = std::to_string (mRunNumber );
273+ w.setMetaData (md);
274+
275+ LOGP (info, " Sending object to DCS DB {}/{} of size {} ({}) bytes, valid for {} : {}" , w.getPath (), w.getFileName (), dataVec.size (), dataStr.str ().size (), w.getStartValidityTimestamp (), w.getEndValidityTimestamp ());
276+
277+ o2::header::DataHeader::SubSpecificationType subSpec{(o2::header::DataHeader::SubSpecificationType)mCalDetMapType + mDCSSpecOffset };
278+ output.snapshot (Output{clbUtils::gDataOriginCDBPayload , " TPC_CALIB_DCS" , subSpec}, dataVec);
279+ output.snapshot (Output{clbUtils::gDataOriginCDBWrapper , " TPC_CALIB_DCS" , subSpec}, w);
280+ };
281+
282+ const auto & pedestals = mMergedCalDetsMap .at (" Pedestals" );
283+ const auto & noise = mMergedCalDetsMap .at (" Noise" );
284+
285+ bool first = true ;
286+ for (auto threshold : {2 .5f , 3 .f , 3 .5f }) {
287+ auto pedestalsThreshold = cru_calib_helpers::preparePedestalFiles (pedestals, noise, {threshold});
288+
289+ // pedestals don't depend on threshold, publish on first iteration only
290+ if (first) {
291+ const auto & pedestalsPhys = pedestalsThreshold[" PedestalsPhys" ];
292+ sendObject (pedestalsPhys, " TPC/Calib/PedestalsPhys" , " Pedestals" );
293+ }
294+
295+ const auto & thresholdsPhys = pedestalsThreshold[" ThresholdMapPhys" ];
296+ const auto fileNameBase = fmt::format (" ThresholdsPhys-{:.0f}" , threshold * 10 );
297+ sendObject (thresholdsPhys, " TPC/Calib/" + fileNameBase, fileNameBase);
298+
299+ first = false ;
300+ }
301+ }
241302};
242303
243- o2::framework::DataProcessorSpec o2::tpc::getCalDetMergerPublisherSpec (uint32_t lanes, bool skipCCDB, bool dumpAfterComplete)
304+ o2::framework::DataProcessorSpec o2::tpc::getCalDetMergerPublisherSpec (uint32_t lanes, bool skipCCDB, bool sendToDCS, bool dumpAfterComplete)
244305{
245306 std::vector<OutputSpec> outputs;
246307 if (!skipCCDB) {
247308 outputs.emplace_back (ConcreteDataTypeMatcher{clbUtils::gDataOriginCDBPayload , " TPC_CALIB" }, Lifetime::Sporadic);
248309 outputs.emplace_back (ConcreteDataTypeMatcher{clbUtils::gDataOriginCDBWrapper , " TPC_CALIB" }, Lifetime::Sporadic);
249310 }
250311
312+ if (sendToDCS) {
313+ outputs.emplace_back (ConcreteDataTypeMatcher{clbUtils::gDataOriginCDBPayload , " TPC_CALIB_DCS" }, Lifetime::Sporadic);
314+ outputs.emplace_back (ConcreteDataTypeMatcher{clbUtils::gDataOriginCDBWrapper , " TPC_CALIB_DCS" }, Lifetime::Sporadic);
315+ }
316+
251317 std::vector<InputSpec> inputs;
252318 inputs.emplace_back (" clbPayload" , ConcreteDataTypeMatcher{gDataOriginTPC , " CLBPART" }, Lifetime::Sporadic);
253319 inputs.emplace_back (" clbInfo" , ConcreteDataTypeMatcher{gDataOriginTPC , " CLBPARTINFO" }, Lifetime::Sporadic);
@@ -258,11 +324,11 @@ o2::framework::DataProcessorSpec o2::tpc::getCalDetMergerPublisherSpec(uint32_t
258324 id.data (),
259325 inputs,
260326 outputs,
261- AlgorithmSpec{adaptFromTask<CalDetMergerPublisherSpec>(lanes, skipCCDB, dumpAfterComplete)},
327+ AlgorithmSpec{adaptFromTask<CalDetMergerPublisherSpec>(lanes, skipCCDB, sendToDCS, dumpAfterComplete)},
262328 Options{
263329 {" force-quit" , VariantType::Bool, false , {" force quit after max-events have been reached" }},
264330 {" direct-file-dump" , VariantType::Bool, false , {" directly dump calibration to file" }},
265331 {" check-calib-infos" , VariantType::Bool, false , {" make consistency check of calib infos" }},
266332 } // end Options
267- }; // end DataProcessorSpec
333+ }; // end DataProcessorSpec
268334}
0 commit comments