Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 10:42:33

0001 /****************************************************************************
0002  *
0003  * This is a part of CTPPS offline software.
0004  * Authors:
0005  *   Edoardo Bossini
0006  *   Filip Dej
0007  *   Laurent Forthomme
0008  *
0009  * NOTE:
0010  *   Given implementation handles calibration files in JSON format,
0011  *   which can be generated using dedicated python script.
0012  *
0013  ****************************************************************************/
0014 
0015 #include "FWCore/Framework/interface/MakerMacros.h"
0016 #include "FWCore/Framework/interface/SourceFactory.h"
0017 #include "FWCore/Framework/interface/ESHandle.h"
0018 #include "FWCore/Framework/interface/ESProducer.h"
0019 #include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
0020 #include "FWCore/Framework/interface/ESProducts.h"
0021 
0022 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0023 
0024 #include "CondFormats/PPSObjects/interface/PPSTimingCalibration.h"
0025 #include "CondFormats/DataRecord/interface/PPSTimingCalibrationRcd.h"
0026 
0027 #include <boost/property_tree/json_parser.hpp>
0028 #include <boost/property_tree/ptree.hpp>
0029 
0030 namespace pt = boost::property_tree;
0031 
0032 //------------------------------------------------------------------------------
0033 
0034 class PPSTimingCalibrationESSource : public edm::ESProducer, public edm::EventSetupRecordIntervalFinder {
0035 public:
0036   PPSTimingCalibrationESSource(const edm::ParameterSet&);
0037 
0038   edm::ESProducts<std::unique_ptr<PPSTimingCalibration> > produce(const PPSTimingCalibrationRcd&);
0039 
0040   static void fillDescriptions(edm::ConfigurationDescriptions&);
0041 
0042 private:
0043   enum struct DetectorType { INVALID = 0, TOTEM_UFSD = 1, PPS_DIAMOND = 2 };
0044 
0045   void setIntervalFor(const edm::eventsetup::EventSetupRecordKey&,
0046                       const edm::IOVSyncValue&,
0047                       edm::ValidityInterval&) override;
0048 
0049   /// Extract calibration data from JSON file (TOTEM vertical)
0050   std::unique_ptr<PPSTimingCalibration> parseTotemUFSDJsonFile() const;
0051   /// Extract calibration data from JSON file (PPS horizontal diamond)
0052   std::unique_ptr<PPSTimingCalibration> parsePPSDiamondJsonFile() const;
0053 
0054   const std::string filename_;
0055   DetectorType subdetector_;
0056 };
0057 
0058 //------------------------------------------------------------------------------
0059 
0060 PPSTimingCalibrationESSource::PPSTimingCalibrationESSource(const edm::ParameterSet& iConfig)
0061     : filename_(iConfig.getParameter<edm::FileInPath>("calibrationFile").fullPath()),
0062       subdetector_((DetectorType)iConfig.getParameter<unsigned int>("subDetector")) {
0063   setWhatProduced(this);
0064   findingRecord<PPSTimingCalibrationRcd>();
0065 }
0066 
0067 //------------------------------------------------------------------------------
0068 
0069 edm::ESProducts<std::unique_ptr<PPSTimingCalibration> > PPSTimingCalibrationESSource::produce(
0070     const PPSTimingCalibrationRcd&) {
0071   switch (subdetector_) {
0072     case DetectorType::TOTEM_UFSD:
0073       return edm::es::products(parseTotemUFSDJsonFile());
0074     case DetectorType::PPS_DIAMOND:
0075       return edm::es::products(parsePPSDiamondJsonFile());
0076     default:
0077       throw cms::Exception("PPSTimingCalibrationESSource") << "Subdetector " << (int)subdetector_ << " not recognised!";
0078   }
0079 }
0080 
0081 //------------------------------------------------------------------------------
0082 
0083 void PPSTimingCalibrationESSource::setIntervalFor(const edm::eventsetup::EventSetupRecordKey&,
0084                                                   const edm::IOVSyncValue&,
0085                                                   edm::ValidityInterval& oValidity) {
0086   oValidity = edm::ValidityInterval(edm::IOVSyncValue::beginOfTime(), edm::IOVSyncValue::endOfTime());
0087 }
0088 
0089 //------------------------------------------------------------------------------
0090 
0091 std::unique_ptr<PPSTimingCalibration> PPSTimingCalibrationESSource::parseTotemUFSDJsonFile() const {
0092   pt::ptree mother_node;
0093   pt::read_json(filename_, mother_node);
0094 
0095   const std::string formula = mother_node.get<std::string>("formula");
0096   PPSTimingCalibration::ParametersMap params;
0097   PPSTimingCalibration::TimingMap time_info;
0098 
0099   for (pt::ptree::value_type& par : mother_node.get_child("parameters")) {
0100     PPSTimingCalibration::Key key;
0101     key.db = (int)strtol(par.first.data(), nullptr, 10);
0102 
0103     for (pt::ptree::value_type& board : par.second) {
0104       key.sampic = board.second.get<int>("sampic");
0105       key.channel = board.second.get<int>("channel");
0106       double timeOffset = board.second.get<double>("time_offset");
0107       double timePrecision = board.second.get<double>("time_precision");
0108       key.cell = -1;
0109       time_info[key] = {timeOffset, timePrecision};
0110 
0111       int cell_ct = 0;
0112       for (pt::ptree::value_type& cell : board.second.get_child("cells")) {
0113         std::vector<double> values;
0114         key.cell = cell_ct;
0115 
0116         for (pt::ptree::value_type& param : cell.second)
0117           values.emplace_back(std::stod(param.second.data(), nullptr));
0118         params[key] = values;
0119         cell_ct++;
0120       }
0121     }
0122   }
0123   return std::make_unique<PPSTimingCalibration>(formula, params, time_info);
0124 }
0125 
0126 std::unique_ptr<PPSTimingCalibration> PPSTimingCalibrationESSource::parsePPSDiamondJsonFile() const {
0127   pt::ptree mother_node;
0128   pt::read_json(filename_, mother_node);
0129 
0130   const std::string formula = mother_node.get<std::string>("formula");
0131   PPSTimingCalibration::ParametersMap params;
0132   PPSTimingCalibration::TimingMap time_info;
0133 
0134   for (pt::ptree::value_type& par : mother_node.get_child("Parameters.Sectors")) {
0135     PPSTimingCalibration::Key key;
0136     key.db = par.second.get<int>("sector");
0137 
0138     for (pt::ptree::value_type& st : par.second.get_child("Stations")) {
0139       key.sampic = st.second.get<int>("station");
0140 
0141       for (pt::ptree::value_type& pl : st.second.get_child("Planes")) {
0142         key.channel = pl.second.get<int>("plane");
0143 
0144         for (pt::ptree::value_type& ch : pl.second.get_child("Channels")) {
0145           key.cell = ch.second.get<int>("channel");
0146           double timeOffset = ch.second.get<double>("time_offset");
0147           double timePrecision = ch.second.get<double>("time_precision");
0148           time_info[key] = {timeOffset, timePrecision};
0149 
0150           std::vector<double> values;
0151           for (pt::ptree::value_type& param : ch.second.get_child("param"))
0152             values.emplace_back(std::stod(param.second.data(), nullptr));
0153           params[key] = values;
0154         }
0155       }
0156     }
0157   }
0158   return std::make_unique<PPSTimingCalibration>(formula, params, time_info);
0159 }
0160 
0161 void PPSTimingCalibrationESSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0162   edm::ParameterSetDescription desc;
0163   desc.add<edm::FileInPath>("calibrationFile", edm::FileInPath())
0164       ->setComment("file with SAMPIC calibrations, ADC and INL; if empty or corrupted, no calibration will be applied");
0165   desc.add<unsigned int>("subDetector", (unsigned int)PPSTimingCalibrationESSource::DetectorType::INVALID)
0166       ->setComment("type of sub-detector for which the calibrations are provided");
0167 
0168   descriptions.add("ppsTimingCalibrationESSource", desc);
0169 }
0170 
0171 DEFINE_FWK_EVENTSETUP_SOURCE(PPSTimingCalibrationESSource);