Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:21:41

0001 /****************************************************************************
0002  *
0003  * This is a part of CTPPS offline software.
0004  * Authors:
0005  *   Laurent Forthomme (laurent.forthomme@cern.ch)
0006  *   Nicola Minafra (nicola.minafra@cern.ch)
0007  *   Filip Dej
0008  *   Christopher Misan (krzysztof.misan@cern.ch)
0009  *
0010  ****************************************************************************/
0011 
0012 #include "RecoPPS/Local/interface/TotemTimingConversions.h"
0013 #include "FWCore/Utilities/interface/Exception.h"
0014 
0015 //----------------------------------------------------------------------------------------------------
0016 
0017 TotemTimingConversions::TotemTimingConversions(double sampicSamplingPeriodNs,
0018                                                bool mergeTimePeaks,
0019                                                const PPSTimingCalibration& calibration)
0020     : calibration_(calibration),
0021       sampicSamplingPeriodNs_(sampicSamplingPeriodNs),
0022       mergeTimePeaks_(mergeTimePeaks),
0023       calibrationFunction_(calibration_.formula()) {}
0024 
0025 //----------------------------------------------------------------------------------------------------
0026 
0027 float TotemTimingConversions::timeOfFirstSample(const TotemTimingDigi& digi) const {
0028   unsigned int offsetOfSamples = digi.eventInfo().offsetOfSamples();
0029 
0030   unsigned int timestamp =
0031       (digi.cellInfo() <= SAMPIC_MAX_NUMBER_OF_SAMPLES / 2) ? digi.timestampA() : digi.timestampB();
0032 
0033   int cell0TimeClock = timestamp + ((digi.fpgaTimestamp() - timestamp) & CELL0_MASK) - digi.eventInfo().l1ATimestamp() +
0034                        digi.eventInfo().l1ALatency();
0035 
0036   // time of first cell
0037   float cell0TimeInstant = SAMPIC_MAX_NUMBER_OF_SAMPLES * sampicSamplingPeriodNs_ * cell0TimeClock;
0038 
0039   // time of triggered cell
0040   float firstCellTimeInstant =
0041       (digi.cellInfo() < offsetOfSamples)
0042           ? cell0TimeInstant + digi.cellInfo() * sampicSamplingPeriodNs_
0043           : cell0TimeInstant - (SAMPIC_MAX_NUMBER_OF_SAMPLES - digi.cellInfo()) * sampicSamplingPeriodNs_;
0044 
0045   int db = digi.hardwareBoardId();
0046   int sampic = digi.hardwareSampicId();
0047   int channel = digi.hardwareChannelId();
0048   float t = firstCellTimeInstant + calibration_.timeOffset(db, sampic, channel);
0049   //NOTE: If no time offset is set, timeOffset returns 0
0050 
0051   if (mergeTimePeaks_) {
0052     if (t < -ACCEPTED_TIME_RADIUS)
0053       t += SAMPIC_MAX_NUMBER_OF_SAMPLES * sampicSamplingPeriodNs_;
0054     if (t > ACCEPTED_TIME_RADIUS)
0055       t -= SAMPIC_MAX_NUMBER_OF_SAMPLES * sampicSamplingPeriodNs_;
0056   }
0057 
0058   return t;
0059 }
0060 
0061 //----------------------------------------------------------------------------------------------------
0062 
0063 float TotemTimingConversions::triggerTime(const TotemTimingDigi& digi) const {
0064   unsigned int offsetOfSamples = digi.eventInfo().offsetOfSamples();
0065   return timeOfFirstSample(digi) + (SAMPIC_MAX_NUMBER_OF_SAMPLES - offsetOfSamples) * sampicSamplingPeriodNs_;
0066 }
0067 
0068 //----------------------------------------------------------------------------------------------------
0069 
0070 float TotemTimingConversions::timePrecision(const TotemTimingDigi& digi) const {
0071   int db = digi.hardwareBoardId();
0072   int sampic = digi.hardwareSampicId();
0073   int channel = digi.hardwareChannelId();
0074   return calibration_.timePrecision(db, sampic, channel);
0075 }
0076 
0077 //----------------------------------------------------------------------------------------------------
0078 
0079 std::vector<float> TotemTimingConversions::timeSamples(const TotemTimingDigi& digi) const {
0080   std::vector<float> time(digi.numberOfSamples());
0081   for (unsigned int i = 0; i < time.size(); ++i)
0082     time.at(i) = timeOfFirstSample(digi) + i * sampicSamplingPeriodNs_;
0083   return time;
0084 }
0085 
0086 //----------------------------------------------------------------------------------------------------
0087 // NOTE: If no proper file is specified, calibration is not applied
0088 
0089 std::vector<float> TotemTimingConversions::voltSamples(const TotemTimingDigi& digi) const {
0090   std::vector<float> data;
0091   if (calibrationFunction_.numberOfVariables() != 1)
0092     for (const auto& sample : digi.samples())
0093       data.emplace_back(SAMPIC_ADC_V * sample);
0094   else {
0095     unsigned int db = digi.hardwareBoardId();
0096     unsigned int sampic = digi.hardwareSampicId();
0097     unsigned int channel = digi.hardwareChannelId();
0098     unsigned int cell = digi.cellInfo();
0099     for (const auto& sample : digi.samples()) {
0100       // ring buffer on Sampic, so accounting for samples register boundary
0101       const unsigned short sample_cell = (cell++) % SAMPIC_MAX_NUMBER_OF_SAMPLES;
0102       auto parameters = calibration_.parameters(db, sampic, channel, sample_cell);
0103       if (parameters.empty() || parameters.size() != calibrationFunction_.numberOfParameters())
0104         throw cms::Exception("TotemTimingConversions:voltSamples")
0105             << "Invalid calibrations retrieved for Sampic digi"
0106             << " (" << db << ", " << sampic << ", " << channel << ", " << sample_cell << ")!";
0107       data.emplace_back(calibrationFunction_.evaluate(std::vector<double>{(double)sample}, parameters));
0108     }
0109   }
0110   return data;
0111 }