Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PPS] Conditions format update for diamond timing calibration #26207

Merged
merged 10 commits into from Mar 26, 2019
Expand Up @@ -39,10 +39,10 @@ class PPSTimingCalibration
formula_( formula ), parameters_( params ), timeInfo_( timeinfo ) {}
~PPSTimingCalibration() = default;

std::vector<double> parameters( int db, int sampic, int channel, int cell ) const;
std::vector<double> parameters( int key1, int key2, int key3, int key4 ) const;
inline const std::string& formula() const { return formula_; }
double timeOffset( int db, int sampic, int channel ) const;
double timePrecision( int db, int sampic, int channel ) const;
double timeOffset( int key1, int key2, int key3, int key4 = -1 ) const;
double timePrecision( int key1, int key2, int key3, int key4 = -1 ) const;

friend std::ostream& operator<<( std::ostream& os, const PPSTimingCalibration& data );

Expand Down
Expand Up @@ -2,6 +2,7 @@
*
* This is a part of CTPPS offline software.
* Authors:
* Edoardo Bossini
* Filip Dej
* Laurent Forthomme
*
Expand Down Expand Up @@ -34,25 +35,35 @@ class PPSTimingCalibrationESSource : public edm::ESProducer, public edm::EventSe
{
public:
PPSTimingCalibrationESSource( const edm::ParameterSet& );
~PPSTimingCalibrationESSource() override = default;

edm::ESProducts<std::unique_ptr<PPSTimingCalibration> > produce( const PPSTimingCalibrationRcd& );

static void fillDescriptions( edm::ConfigurationDescriptions& );

private:
enum struct DetectorType
{
INVALID = 0,
TOTEM_UFSD = 1,
PPS_DIAMOND = 2
};

void setIntervalFor( const edm::eventsetup::EventSetupRecordKey&, const edm::IOVSyncValue&, edm::ValidityInterval& ) override;

/// Extract calibration data from JSON file
std::unique_ptr<PPSTimingCalibration> parseJsonFile() const;
/// Extract calibration data from JSON file (TOTEM vertical)
std::unique_ptr<PPSTimingCalibration> parseTotemUFSDJsonFile() const;
/// Extract calibration data from JSON file (PPS horizontal diamond)
std::unique_ptr<PPSTimingCalibration> parsePPSDiamondJsonFile() const;

const std::string filename_;
DetectorType subdetector_;
};

//------------------------------------------------------------------------------

PPSTimingCalibrationESSource::PPSTimingCalibrationESSource( const edm::ParameterSet& iConfig ) :
filename_( iConfig.getParameter<edm::FileInPath>( "calibrationFile" ).fullPath() )
filename_ ( iConfig.getParameter<edm::FileInPath>( "calibrationFile" ).fullPath() ),
subdetector_( (DetectorType)iConfig.getParameter<unsigned int>( "subDetector" ) )
{
setWhatProduced( this );
findingRecord<PPSTimingCalibrationRcd>();
Expand All @@ -63,7 +74,15 @@ PPSTimingCalibrationESSource::PPSTimingCalibrationESSource( const edm::Parameter
edm::ESProducts<std::unique_ptr<PPSTimingCalibration> >
PPSTimingCalibrationESSource::produce( const PPSTimingCalibrationRcd& )
{
return edm::es::products( parseJsonFile() );
switch ( subdetector_ ) {
case DetectorType::TOTEM_UFSD:
return edm::es::products( parseTotemUFSDJsonFile() );
case DetectorType::PPS_DIAMOND:
return edm::es::products( parsePPSDiamondJsonFile() );
default:
throw cms::Exception( "PPSTimingCalibrationESSource" )
<< "Subdetector " << (int)subdetector_ << " not recognised!";
}
}

//------------------------------------------------------------------------------
Expand All @@ -79,20 +98,20 @@ PPSTimingCalibrationESSource::setIntervalFor( const edm::eventsetup::EventSetupR
//------------------------------------------------------------------------------

std::unique_ptr<PPSTimingCalibration>
PPSTimingCalibrationESSource::parseJsonFile() const
PPSTimingCalibrationESSource::parseTotemUFSDJsonFile() const
{
pt::ptree node;
pt::read_json( filename_, node );
pt::ptree mother_node;
pt::read_json( filename_, mother_node );

const std::string formula = node.get<std::string>( "formula" );
const std::string formula = mother_node.get<std::string>( "formula" );
PPSTimingCalibration::ParametersMap params;
PPSTimingCalibration::TimingMap time_info;

for ( pt::ptree::value_type& par : node.get_child( "parameters" ) ) {
for ( pt::ptree::value_type& par : mother_node.get_child( "parameters" ) ) {
PPSTimingCalibration::Key key;
key.db = (int)strtol( par.first.data(), nullptr, 10 );

for (pt::ptree::value_type &board : par.second) {
for ( pt::ptree::value_type& board : par.second ) {
key.sampic = board.second.get<int>( "sampic" );
key.channel = board.second.get<int>( "channel" );
double timeOffset = board.second.get<double>( "time_offset" );
Expand All @@ -101,7 +120,7 @@ PPSTimingCalibrationESSource::parseJsonFile() const
time_info[key] = { timeOffset, timePrecision };

int cell_ct = 0;
for ( pt::ptree::value_type &cell : board.second.get_child( "cells" ) ) {
for ( pt::ptree::value_type& cell : board.second.get_child( "cells" ) ) {
std::vector<double> values;
key.cell = cell_ct;

Expand All @@ -115,12 +134,51 @@ PPSTimingCalibrationESSource::parseJsonFile() const
return std::make_unique<PPSTimingCalibration>( formula, params, time_info );
}

std::unique_ptr<PPSTimingCalibration>
PPSTimingCalibrationESSource::parsePPSDiamondJsonFile() const
{
pt::ptree mother_node;
pt::read_json( filename_, mother_node );

const std::string formula = mother_node.get<std::string>( "formula" );
PPSTimingCalibration::ParametersMap params;
PPSTimingCalibration::TimingMap time_info;

for ( pt::ptree::value_type& par : mother_node.get_child( "Parameters.Sectors" ) ) {
PPSTimingCalibration::Key key;
key.db = par.second.get<int>( "sector" );

for ( pt::ptree::value_type& st : par.second.get_child( "Stations" ) ) {
key.sampic = st.second.get<int>( "station" );

for ( pt::ptree::value_type& pl : st.second.get_child( "Planes" ) ) {
key.channel = pl.second.get<int>( "plane" );

for ( pt::ptree::value_type& ch : pl.second.get_child( "Channels" ) ) {
key.cell = ch.second.get<int>( "channel" );
double timeOffset = ch.second.get<double>( "time_offset" );
double timePrecision = ch.second.get<double>( "time_precision" );
time_info[key] = { timeOffset, timePrecision };

std::vector<double> values;
for ( pt::ptree::value_type& param : ch.second.get_child( "param" ) )
values.emplace_back( std::stod( param.second.data(), nullptr ) );
params[key] = values;
}
}
}
}
return std::make_unique<PPSTimingCalibration>( formula, params, time_info );
}

void
PPSTimingCalibrationESSource::fillDescriptions( edm::ConfigurationDescriptions& descriptions )
{
edm::ParameterSetDescription desc;
desc.add<edm::FileInPath>( "calibrationFile", edm::FileInPath() )
->setComment( "file with SAMPIC calibrations, ADC and INL; if empty or corrupted, no calibration will be applied" );
desc.add<unsigned int>( "subDetector", (unsigned int)PPSTimingCalibrationESSource::DetectorType::INVALID )
->setComment( "type of sub-detector for which the calibrations are provided" );

descriptions.add( "ppsTimingCalibrationESSource", desc );
}
Expand Down
@@ -0,0 +1,5 @@
class PPSTimingDetEnum:
INVALID = 0
TOTEM_UFSD = 1
PPS_DIAMOND = 2

16 changes: 7 additions & 9 deletions CondFormats/CTPPSReadoutObjects/src/PPSTimingCalibration.cc
Expand Up @@ -34,29 +34,29 @@ operator<<( std::ostream& os, const PPSTimingCalibration::Key& key )
//--------------------------------------------------------------------------

std::vector<double>
PPSTimingCalibration::parameters( int db, int sampic, int channel, int cell ) const
PPSTimingCalibration::parameters( int key1, int key2, int key3, int key4 ) const
{
Key key{ db, sampic, channel, cell };
Key key{ key1, key2, key3, key4 };
auto out = parameters_.find( key );
if ( out == parameters_.end() )
return {};
return out->second;
}

double
PPSTimingCalibration::timeOffset( int db, int sampic, int channel ) const
PPSTimingCalibration::timeOffset( int key1, int key2, int key3, int key4 ) const
{
Key key{ db, sampic, channel, -1 };
Key key{ key1, key2, key3, key4 };
auto out = timeInfo_.find( key );
if ( out == timeInfo_.end() )
return 0.;
return out->second.first;
}

double
PPSTimingCalibration::timePrecision( int db, int sampic, int channel ) const
PPSTimingCalibration::timePrecision( int key1, int key2, int key3, int key4 ) const
{
Key key{ db, sampic, channel, -1 };
Key key{ key1, key2, key3, key4 };
auto out = timeInfo_.find( key );
if ( out == timeInfo_.end() )
return 0.;
Expand All @@ -71,9 +71,7 @@ operator<<( std::ostream& os, const PPSTimingCalibration& data )
os << kv.first <<" [";
for ( size_t i = 0; i < kv.second.size(); ++i )
os << ( i > 0 ? ", " : "" ) << kv.second.at( i );
PPSTimingCalibration::Key k = kv.first;
k.cell = -1;
const auto& time = data.timeInfo_.at( k );
const auto& time = data.timeInfo_.at( kv.first );
os << "] " << time.first << " " << time.second << "\n";
}
return os;
Expand Down
4 changes: 2 additions & 2 deletions CondTools/CTPPS/test/ppsTimingCalibrationAnalyzer_cfg.py
Expand Up @@ -20,15 +20,15 @@

# load calibrations from database
process.load('CondCore.CondDB.CondDB_cfi')
process.CondDB.connect = 'sqlite_file:totemTiming_calibration.sqlite' # SQLite input
process.CondDB.connect = 'sqlite_file:ppsDiamondTiming_calibration.sqlite' # SQLite input

process.PoolDBESSource = cms.ESSource('PoolDBESSource',
process.CondDB,
DumpStats = cms.untracked.bool(True),
toGet = cms.VPSet(
cms.PSet(
record = cms.string('PPSTimingCalibrationRcd'),
tag = cms.string('TotemTimingCalibration')
tag = cms.string('PPSDiamondTimingCalibration')
)
)
)
Expand Down
11 changes: 6 additions & 5 deletions CondTools/CTPPS/test/ppsTimingCalibrationWriter_cfg.py
Expand Up @@ -9,23 +9,24 @@
interval = cms.uint64(1)
)

from CondFormats.CTPPSReadoutObjects.PPSTimingDetEnum_cff import PPSTimingDetEnum

# load calibrations from JSON file
process.load('CondFormats.CTPPSReadoutObjects.ppsTimingCalibrationESSource_cfi')
process.ppsTimingCalibrationESSource.calibrationFile = cms.FileInPath('RecoCTPPS/TotemRPLocal/data/timing_offsets_ufsd_2018.dec18.cal.json')
process.ppsTimingCalibrationESSource.calibrationFile = cms.FileInPath('RecoCTPPS/TotemRPLocal/data/timing_calibration_diamond_2018_mar19.ex.json')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@forthommel related to your comment cms-data/RecoCTPPS-TotemRPLocal#3 (comment) : I understand this is just a test, but if that file is not merged the test will be broken and in practice useless. Will json files be routinely used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are perfectly right. As it is now, this test is only used as a method to produce the sqlite payload prior to filling the database, therefore only indirectly in production. Same comment for the ESProducer itself. So no, theses JSON files will not be routinely used in production.

process.ppsTimingCalibrationESSource.subDetector = PPSTimingDetEnum.PPS_DIAMOND

# output service for database
process.load('CondCore.CondDB.CondDB_cfi')
process.CondDB.connect = 'sqlite_file:totemTiming_calibration.sqlite' # SQLite output
#process.CondDB.connect = 'oracle://cmsprep/TimingCalibration' # Oracle output
#process.CondDB.connect = 'frontier://cmsfrontier.cern.ch:8000/FrontierPrep/TimingCalibration' # Frontier output
process.CondDB.connect = 'sqlite_file:ppsDiamondTiming_calibration.sqlite' # SQLite output

process.PoolDBOutputService = cms.Service('PoolDBOutputService',
process.CondDB,
timetype = cms.untracked.string('runnumber'),
toPut = cms.VPSet(
cms.PSet(
record = cms.string('PPSTimingCalibrationRcd'),
tag = cms.string('TotemTimingCalibration'),
tag = cms.string('PPSDiamondTimingCalibration'),
)
)
)
Expand Down