CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TotemTimingRecHitProducerAlgorithm.cc
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * This is a part of CTPPS offline software.
4  * Authors:
5  * Laurent Forthomme (laurent.forthomme@cern.ch)
6  * Nicola Minafra
7  * Christopher Misan (krzysztof.misan@cern.ch)
8  *
9  ****************************************************************************/
10 
12 
14 
15 #include <memory>
16 
17 #include <numeric>
18 
19 //----------------------------------------------------------------------------------------------------
20 
22  : mergeTimePeaks_(iConfig.getParameter<bool>("mergeTimePeaks")),
23  baselinePoints_(iConfig.getParameter<int>("baselinePoints")),
24  saturationLimit_(iConfig.getParameter<double>("saturationLimit")),
25  cfdFraction_(iConfig.getParameter<double>("cfdFraction")),
26  smoothingPoints_(iConfig.getParameter<int>("smoothingPoints")),
27  lowPassFrequency_(iConfig.getParameter<double>("lowPassFrequency")),
28  hysteresis_(iConfig.getParameter<double>("hysteresis")),
29  sampicOffset_(iConfig.getParameter<double>("sampicOffset")),
30  sampicSamplingPeriodNs_(iConfig.getParameter<double>("sampicSamplingPeriodNs")) {}
31 
32 //----------------------------------------------------------------------------------------------------
33 
35  sampicConversions_ = std::make_unique<TotemTimingConversions>(sampicSamplingPeriodNs_, mergeTimePeaks_, calib);
36 }
37 
38 //----------------------------------------------------------------------------------------------------
39 
43  for (const auto& vec : input) {
44  const CTPPSDetId detid(vec.detId());
45 
46  float x_pos = 0.f, y_pos = 0.f, z_pos = 0.f;
47  float x_width = 0.f, y_width = 0.f, z_width = 0.f;
48 
49  // retrieve the geometry element associated to this DetID ( if present )
50  const DetGeomDesc* det = geom.sensorNoThrow(detid);
51 
52  if (det) {
53  x_pos = det->translation().x();
54  y_pos = det->translation().y();
55  z_pos = det->parentZPosition(); // retrieve the plane position;
56 
57  const auto& diamondDimensions = det->getDiamondDimensions();
58  x_width = 2.0 * diamondDimensions.xHalfWidth; // parameters stand for half the size
59  y_width = 2.0 * diamondDimensions.yHalfWidth;
60  z_width = 2.0 * diamondDimensions.zHalfWidth;
61  } else
62  throw cms::Exception("TotemTimingRecHitProducerAlgorithm") << "Failed to retrieve a sensor for " << detid;
63 
64  if (!sampicConversions_)
65  throw cms::Exception("TotemTimingRecHitProducerAlgorithm") << "No timing conversion retrieved.";
66 
67  edm::DetSet<TotemTimingRecHit>& rec_hits = output.find_or_insert(detid);
68 
69  for (const auto& digi : vec) {
70  const float triggerCellTimeInstant(sampicConversions_->triggerTime(digi));
71  const float timePrecision(sampicConversions_->timePrecision(digi));
72  const std::vector<float> time(sampicConversions_->timeSamples(digi));
73  std::vector<float> data(sampicConversions_->voltSamples(digi));
74 
75  auto [min_it, max_it] = std::minmax_element(data.begin(), data.end());
76 
77  if (det->name() == "CTPPS_Diamond_Segment") {
78  //flip the signal
79  for (unsigned int i = 0; i < data.size(); ++i)
80  data[i] = -data[i] + sampicOffset_;
81  }
82  RegressionResults baselineRegression = simplifiedLinearRegression(time, data, 0, baselinePoints_);
83 
84  // remove baseline
85  std::vector<float> dataCorrected(data.size());
86  for (unsigned int i = 0; i < data.size(); ++i)
87  dataCorrected[i] = data[i] - (baselineRegression.q + baselineRegression.m * time[i]);
88 
89  auto max_corrected_it = std::max_element(dataCorrected.begin(), dataCorrected.end());
90 
92 
93  //if det==diamond then if (*min_it) > saturationLimit_), calculate the t, otherwise t=-100
94  //if det==ufsd then if (*max_it) < saturationLimit_), calculate the t, otherwise t=-100
95  //the difference between ufsd and sampic conditions comes from the signal flip
96  if ((det->name() == "CTPPS_Diamond_Segment" && (*min_it) > saturationLimit_) ||
97  (det->name() == "CTPPS_UFSD_Segment" && (*max_it) < saturationLimit_))
98  t = constantFractionDiscriminator(time, dataCorrected);
100  rec_hits.emplace_back(x_pos,
101  x_width,
102  y_pos,
103  y_width,
104  z_pos,
105  z_width,
106  t,
107  triggerCellTimeInstant,
108  timePrecision,
109  *max_corrected_it,
110  baselineRegression.rms,
111  mode_);
112  }
113  }
114 }
115 
116 //----------------------------------------------------------------------------------------------------
117 
119  const std::vector<float>& time,
120  const std::vector<float>& data,
121  const unsigned int start_at,
122  const unsigned int points) const {
124  if (time.size() != data.size())
125  return results;
126  if (start_at > time.size())
127  return results;
128  unsigned int stop_at = std::min((unsigned int)time.size(), start_at + points);
129  unsigned int realPoints = stop_at - start_at;
130  auto t_begin = std::next(time.begin(), start_at);
131  auto t_end = std::next(time.begin(), stop_at);
132  auto d_begin = std::next(data.begin(), start_at);
133  auto d_end = std::next(data.begin(), stop_at);
134 
135  const float sx = std::accumulate(t_begin, t_end, 0.);
136  const float sxx = std::inner_product(t_begin, t_end, t_begin, 0.); // sum(t**2)
137  const float sy = std::accumulate(d_begin, d_end, 0.);
138 
139  float sxy = 0.;
140  for (unsigned int i = 0; i < realPoints; ++i)
141  sxy += time[i] * data[i];
142 
143  // y = mx + q
144  results.m = (sxy * realPoints - sx * sy) / (sxx * realPoints - sx * sx);
145  results.q = sy / realPoints - results.m * sx / realPoints;
146 
147  float correctedSyy = 0.;
148  for (unsigned int i = 0; i < realPoints; ++i)
149  correctedSyy += pow(data[i] - (results.m * time[i] + results.q), 2);
150  results.rms = sqrt(correctedSyy / realPoints);
151 
152  return results;
153 }
154 
155 //----------------------------------------------------------------------------------------------------
156 
157 int TotemTimingRecHitProducerAlgorithm::fastDiscriminator(const std::vector<float>& data, float threshold) const {
158  int threholdCrossingIndex = -1;
159  bool above = false;
160  bool lockForHysteresis = false;
161 
162  for (unsigned int i = 0; i < data.size(); ++i) {
163  // Look for first edge
164  if (!above && !lockForHysteresis && data[i] > threshold) {
165  threholdCrossingIndex = i;
166  above = true;
167  lockForHysteresis = true;
168  }
169  if (above && lockForHysteresis) // NOTE: not else if!, "above" can be set in
170  // the previous if
171  {
172  // Lock until above threshold_+hysteresis
173  if (lockForHysteresis && data[i] > threshold + hysteresis_)
174  lockForHysteresis = false;
175  // Ignore noise peaks
176  if (lockForHysteresis && data[i] < threshold) {
177  above = false;
178  lockForHysteresis = false;
179  threholdCrossingIndex = -1; // assigned because of noise
180  }
181  }
182  }
183 
184  return threholdCrossingIndex;
185 }
186 
188  const std::vector<float>& data) {
189  std::vector<float> dataProcessed(data);
190  if (lowPassFrequency_ != 0) // Smoothing
191  for (unsigned short i = 0; i < data.size(); ++i)
192  for (unsigned short j = -smoothingPoints_ / 2; j <= +smoothingPoints_ / 2; ++j)
193  if ((i + j) >= 0 && (i + j) < data.size() && j != 0) {
195  dataProcessed[i] += data[i + j] * std::sin(x) / x;
196  }
197  auto max_it = std::max_element(dataProcessed.begin(), dataProcessed.end());
198  float max = *max_it;
199 
200  float threshold = cfdFraction_ * max;
201  int indexOfThresholdCrossing = fastDiscriminator(dataProcessed, threshold);
202 
203  //--- necessary sanity checks before proceeding with the extrapolation
204  return (indexOfThresholdCrossing >= 1 && indexOfThresholdCrossing >= baselinePoints_ &&
205  indexOfThresholdCrossing < (int)time.size())
206  ? (time[indexOfThresholdCrossing - 1] - time[indexOfThresholdCrossing]) /
207  (dataProcessed[indexOfThresholdCrossing - 1] - dataProcessed[indexOfThresholdCrossing]) *
208  (threshold - dataProcessed[indexOfThresholdCrossing]) +
209  time[indexOfThresholdCrossing]
211 }
const Translation & translation() const
Definition: DetGeomDesc.h:80
dictionary results
const DiamondDimensions & getDiamondDimensions() const
Definition: DetGeomDesc.h:90
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
static std::string const input
Definition: EdmProvDump.cc:47
reference find_or_insert(det_id_type id)
Definition: DetSetVector.h:234
const DetGeomDesc * sensorNoThrow(unsigned int id) const noexcept
decltype(auto) emplace_back(Args &&...args)
Definition: DetSet.h:68
float constantFractionDiscriminator(const std::vector< float > &time, const std::vector< float > &data)
T sqrt(T t)
Definition: SSEVec.h:19
int fastDiscriminator(const std::vector< float > &data, float threshold) const
TotemTimingRecHitProducerAlgorithm(const edm::ParameterSet &conf)
void build(const CTPPSGeometry &, const edm::DetSetVector< TotemTimingDigi > &, edm::DetSetVector< TotemTimingRecHit > &)
RegressionResults simplifiedLinearRegression(const std::vector< float > &time, const std::vector< float > &data, const unsigned int start_at, const unsigned int points) const
The manager class for TOTEM RP geometry.
Definition: CTPPSGeometry.h:30
const std::string & name() const
Definition: DetGeomDesc.h:73
float parentZPosition() const
Definition: DetGeomDesc.h:106
Base class for CTPPS detector IDs.
Definition: CTPPSDetId.h:32
std::unique_ptr< TotemTimingConversions > sampicConversions_
void setCalibration(const PPSTimingCalibration &)
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:79
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29