ATLAS Offline Software
CscSplitClusterFitter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <iomanip>
8 #include <sstream>
9 
14 
16 using Muon::CscPrepData;
19 
22 using Results = std::vector<Result>;
23 
24 namespace {
27 }
28 
29 //******************************************************************************
30 
31 CscSplitClusterFitter::CscSplitClusterFitter(const std::string& type, const std::string& aname, const IInterface* parent) :
33  declareInterface<ICscClusterFitter>(this);
34  declareProperty("min_dist", m_min_dist = 2); // Minimum distance between peaks and valley
35  declareProperty("max_qratio", m_max_qratio = 0.15); // Maximum charge ratio between peak strip and valley strip
36 }
37 
38 //**********************************************************************
39 
41  ATH_MSG_DEBUG("Initalizing " << name());
42 
43  ATH_CHECK(m_idHelperSvc.retrieve());
44 
45  // Retrieve the default cluster fitting tool.
47 
48  ATH_MSG_DEBUG("CscClusterization " << name() << ": retrieved " << m_pfitter_def);
49 
50  // Retrieve the precision cluster fitting tool.
52 
53  ATH_MSG_DEBUG("CscClusterization " << name() << ": retrieved " << m_pfitter_prec);
54 
55  ATH_MSG_DEBUG("Properties for " << name() << ":");
56  ATH_MSG_DEBUG(" Default cluster fitter is " << m_pfitter_def.typeAndName());
57  ATH_MSG_DEBUG(" Precision cluster fitter is " << m_pfitter_prec.typeAndName());
58  ATH_MSG_DEBUG(" Min dist peak to valley: " << m_min_dist);
59  ATH_MSG_DEBUG(" Max qratio qval / qpeak: " << m_max_qratio);
60 
61  return StatusCode::SUCCESS;
62 }
63 //**********************************************************************
64 
67  // Check input has at least three strips.
68  unsigned int nstrip = sfits.size();
69  // Use the first strip to extract the layer parameters.
70  const CscStripPrepData* pstrip = sfits[0].strip;
71  Identifier idStrip0 = pstrip->identify();
72  bool measphi = m_idHelperSvc->cscIdHelper().CscIdHelper::measuresPhi(idStrip0);
73 
74  // Display input strips.
75  ATH_MSG_DEBUG("CscStrip fittter input has " << nstrip << " strips");
76 
77  for (unsigned int istrip = 0; istrip < nstrip; ++istrip) {
78  Identifier id = sfits[istrip].strip->identify();
79  ATH_MSG_VERBOSE(" " << istrip << " " << m_idHelperSvc->cscIdHelper().strip(id) << " " << sfits[istrip].charge);
80  }
81  // Find the peak strip and valley strip
82  // Loop over strips
83  std::vector<float> istrip_peaks;
84  std::vector<float> istrip_vals;
85 
86  // Start peak all the time...
87  for (unsigned int istrip = 1; istrip < nstrip - 1; ++istrip) {
88  StripFit sfit = sfits[istrip];
89  float qthis = sfit.charge;
90  float qlast = sfits[istrip - 1].charge;
91  float qnext = sfits[istrip + 1].charge;
92  // Peak at first
93  if (istrip == 1 && qlast > qthis) istrip_peaks.push_back(0);
94  // Peak at last
95  if (istrip + 2 == nstrip && qthis < qnext) istrip_peaks.push_back(nstrip - 1);
96  // Peak if the adjacent strips have less charge.
97  bool ispeak = qthis > qlast && qthis > qnext;
98  bool isval = qthis < qlast && qthis < qnext;
99  // Record if peak.
100 
101  if (ispeak) istrip_peaks.push_back(istrip);
102  if (isval) istrip_vals.push_back(istrip);
103  if (ispeak || isval) continue;
104 
105  // It's only for istrip==1 and 0th and 1st charges are same....
106  if (istrip == 1 && qlast == qthis) {
107  float nstripsameCharge = 2.;
108  unsigned int theStrip = 0;
109  for (unsigned int mstrip = istrip + 1; mstrip < nstrip - 1; ++mstrip) {
110  theStrip = mstrip;
111  if (qthis == sfits[mstrip].charge)
112  nstripsameCharge += 1.;
113  else
114  break;
115  }
116  ispeak = (qthis > sfits[theStrip].charge);
117  isval = (qthis < sfits[theStrip].charge);
118  float offset = 0.5 * (nstripsameCharge - 1);
119  if (ispeak) istrip_peaks.push_back(offset);
120  // We want to start peak all the time...
121  // if ( isval ) istrip_vals.push_back(offset);
122  istrip += int(nstripsameCharge) - 2;
123  continue;
124  }
125 
126  // Special case: next strip has the same charge.
127  // Require the previous strip has less charge and the next following
128  // strip be absent or have less charge.
129  if (qthis == qnext) {
130  float nstripsameCharge = 2.;
131  unsigned int theStrip = 0;
132  bool sameCharge = 1;
133  for (unsigned int mstrip = istrip + 2; mstrip < nstrip - 1; ++mstrip) {
134  theStrip = mstrip;
135  if (qthis == sfits[mstrip].charge)
136  nstripsameCharge += 1.;
137  else {
138  sameCharge = 0;
139  break;
140  }
141  }
142  if (sameCharge) {
143  ispeak = (qthis > qlast);
144  isval = (qthis < qlast);
145  } else {
146  ispeak = (qthis > qlast) && (qthis > sfits[theStrip].charge);
147  isval = (qthis < qlast) && (qthis < sfits[theStrip].charge);
148  }
149  float offset = 0.5 * (nstripsameCharge - 1);
150  if (ispeak) istrip_peaks.push_back(istrip + offset);
151  if (isval) istrip_vals.push_back(istrip + offset);
152  istrip += int(nstripsameCharge) - 1;
153  continue;
154  }
155  }
156 
157  ATH_MSG_DEBUG(" #Peak is " << istrip_peaks.size());
158 
159  // Decide in which valley strip we split cluster
160  // Starting from Peak all the time!!!
161  // Regular case : #peaks - #vals =1
162  // If #peaks == $vals, avoid it at the end of vals..
163 
164  std::vector<unsigned int> splitOnValley;
165  for (unsigned int ival = 0; ival < istrip_vals.size() && ival + 1 < istrip_peaks.size(); ++ival) {
166  // Set initial strip position.
167  float istrip_peak0 = istrip_peaks[ival];
168  float istrip_peak1 = istrip_peaks[ival + 1];
169  float istrip_val = istrip_vals[ival];
170 
171  float dist_ptov = istrip_val - istrip_peak0;
172  float dist_vtop = istrip_peak1 - istrip_val;
173 
174  ATH_MSG_DEBUG(" [ " << istrip_peak0 << ", " << istrip_val << ", " << istrip_peak1 << "] "
175  << "dist p2v:v2p " << dist_ptov << " : " << dist_vtop);
176 
177  if (dist_ptov < 0 || dist_vtop < 0) {
178  ATH_MSG_WARNING(" Peak-to-Val dist is " << dist_ptov << " Val-to-Peak dist is " << dist_vtop
179  << " Shouldnot be negative value :" << istrip_peak0 << " " << istrip_val << " "
180  << istrip_peak1);
181  }
182 
183  float qlpeak = sfits[int(istrip_peak0)].charge;
184  float qval = sfits[int(istrip_val)].charge;
185  float qrpeak = sfits[int(istrip_peak1)].charge;
186 
187  ATH_MSG_DEBUG("qlpk:qval:qrpk " << qlpeak << " " << qval << " " << qrpeak << " " << qval / qlpeak << " " << qval / qrpeak
188  << " " << m_max_qratio);
189 
190  if (dist_ptov < m_min_dist || dist_vtop < m_min_dist || qval / qlpeak > m_max_qratio || qval / qrpeak > m_max_qratio)
191  splitOnValley.push_back(0);
192  else
193  splitOnValley.push_back(1);
194  }
195 
196  unsigned int cnt = 0;
197  for (unsigned int ii = 0; ii < splitOnValley.size(); ii++)
198  if (splitOnValley[ii] == 1) cnt++;
199 
200  if (cnt == 0) {
201  ATH_MSG_DEBUG("No split cluster ");
203  res.fitStatus = 6;
204  res.clusterStatus = Muon::CscStatusWide;
205  results.push_back(res);
206  return results;
207  }
208  ATH_MSG_DEBUG("Cluster is split ");
209 
210  // For the last cluster and strip
211  unsigned int nvals = splitOnValley.size();
212  if (istrip_vals[nvals - 1] != nstrip - 1) {
213  istrip_vals.push_back(nstrip - 1);
214  splitOnValley.push_back(1);
215  nvals = splitOnValley.size();
216  }
217 
218  // if (splitOnValley.size() != istrip_peaks.size())
219  // ATH_MSG_ERROR << " splitOnValley.size() should be same as istrip_peaks.size()" );
220 
221  // Rearrange strips to submit in fitter
222  StripFitList sfits_split;
223  unsigned int firstStripID = 0;
224  unsigned int thisfirstStripID = 0;
225  for (unsigned int isplit = 0; isplit < nvals; ++isplit) {
226  if (splitOnValley[isplit]) {
227  sfits_split.clear();
228 
229  for (unsigned int ist = firstStripID; ist <= istrip_vals[isplit]; ++ist) {
230  ATH_MSG_DEBUG(ist << " " << firstStripID << " " << istrip_vals << " lsplit " << splitOnValley);
231 
232  sfits_split.push_back(sfits[ist]);
233  }
234  // unsigned int split_nstrip = istrip_vals[isplit]-firstStripID;
235  // bool ledge = (isplit==0 && strip0 <=0) ? 1 : 0;
236  // bool redge = (isplit==nvals-1 && strip0+nstrip>maxstrip) ? 1 : 0;
237 
238  thisfirstStripID = firstStripID;
239  firstStripID = int(istrip_vals[isplit]);
240 
241  int fitresult = 99;
242  std::vector<ICscClusterFitter::Result> local_results;
244  // Precision fit.
245  if (!measphi && m_pfitter_prec) {
246  ATH_MSG_VERBOSE(" In CscSplit performing precision fit with " << m_pfitter_prec);
247 
248  local_results = m_pfitter_prec->fit(sfits_split);
249  res = local_results[0];
250  fitresult = res.fitStatus;
251  if (fitresult) {
252  ATH_MSG_VERBOSE(" Precision fit failed: return=" << fitresult);
253  } else {
254  ATH_MSG_VERBOSE(" Precision fit succeeded");
255  }
256  }
257 
258  int prec_fitresult = fitresult;
259  CscClusterStatus oldclustatus = res.clusterStatus;
260  // Default fit.
261  if (fitresult) { // including measphi case
262  ATH_MSG_VERBOSE(" Performing default fit with " << m_pfitter_def);
263  local_results = m_pfitter_def->fit(sfits_split);
264  res = local_results[0];
265  fitresult = res.fitStatus;
266  if (fitresult) {
267  ATH_MSG_VERBOSE(" Default fit failed: return=" << fitresult);
268  } else {
269  ATH_MSG_VERBOSE(" Default fit succeeded");
270  }
271  // Keep the status from the first fit if it is defined.
272  if (oldclustatus != Muon::CscStatusUndefined) res.clusterStatus = oldclustatus;
273  }
274 
275  if (prec_fitresult) { // precision fitter is failed...
276  res.fitStatus = 20 + prec_fitresult;
277 
278  if (oldclustatus == Muon::CscStatusSimple)
279  res.clusterStatus = Muon::CscStatusSplitSimple;
280  else if (oldclustatus == Muon::CscStatusEdge)
281  res.clusterStatus = Muon::CscStatusSplitEdge;
282  else if (oldclustatus == Muon::CscStatusMultiPeak)
283  res.clusterStatus = Muon::CscStatusSplitMultiPeak;
284  else if (oldclustatus == Muon::CscStatusNarrow)
285  res.clusterStatus = Muon::CscStatusSplitNarrow;
286  else if (oldclustatus == Muon::CscStatusWide)
287  res.clusterStatus = Muon::CscStatusSplitWide;
288  else if (oldclustatus == Muon::CscStatusSkewed)
289  res.clusterStatus = Muon::CscStatusSplitSkewed;
290  else if (oldclustatus == Muon::CscStatusQratInconsistent)
292  else if (oldclustatus == Muon::CscStatusStripFitFailed)
293  res.clusterStatus = Muon::CscStatusSplitStripFitFailed;
294  else if (oldclustatus == Muon::CscStatusSaturated)
295  res.clusterStatus = Muon::CscStatusSplitSaturated;
296 
297  } else { // precision fit is successful
298  res.fitStatus = 20;
299  res.clusterStatus = Muon::CscStatusSplitUnspoiled;
300  }
301  // strip in Result class is filled by Qrat or SimpleClusterFitter which is only relevant to the cluster
302  // passed by CscSplitCluster. This should be corrected here.
303  // fstrip and lstrip should be defined in CscSplitClusterFitter but not for the other fitter.
304  res.strip = res.strip + thisfirstStripID;
305  res.fstrip = res.fstrip + thisfirstStripID;
306  res.lstrip = res.lstrip + thisfirstStripID;
307 
308  ATH_MSG_DEBUG(" res.fitStatus " << res.fitStatus << " fitresult " << fitresult);
309 
310  results.push_back(res);
311  }
312  } // for
313 
314  return results;
315 }
316 
317 //**********************************************************************
318 
319 Results CscSplitClusterFitter::fit(const StripFitList& sfits, double) const { return fit(sfits); }
320 
321 //**********************************************************************
322 double CscSplitClusterFitter::getCorrectedError(const CscPrepData* /*pclu*/, double /*slope*/) const { return 0; }
CSS
@ CSS
Definition: ParabolaCscClusterFitter.h:25
ICscClusterFitter::Results
std::vector< Result > Results
Definition: ICscClusterFitter.h:101
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
CSS_ETA
@ CSS_ETA
Definition: ParabolaCscClusterFitter.h:26
Muon::CscStatusSplitSkewed
@ CscStatusSplitSkewed
Skewed, e.g.
Definition: CscClusterStatus.h:80
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
ICscStripFitter::Result::charge
double charge
Definition: ICscStripFitter.h:31
CscStripPrepData.h
ATH_CHECK_RECOVERABLE
#define ATH_CHECK_RECOVERABLE
Evaluate an expression and check for errors.
Definition: AthCheckMacros.h:48
DataNames
ICscClusterFitter::DataNames DataNames
Definition: CscSplitClusterFitter.cxx:20
Muon::CscStatusSplitNarrow
@ CscStatusSplitNarrow
Too narrow after split cluster.
Definition: CscClusterStatus.h:74
Muon::CscStatusSplitSimple
@ CscStatusSplitSimple
Cluster with non-precision fit after split cluster.
Definition: CscClusterStatus.h:63
MuonGM::CscReadoutElement
Definition: CscReadoutElement.h:56
CSS_PHI
@ CSS_PHI
Definition: ParabolaCscClusterFitter.h:26
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
CSL_ETA
@ CSL_ETA
Definition: ParabolaCscClusterFitter.h:26
CscSplitClusterFitter::m_pfitter_def
ToolHandle< ICscClusterFitter > m_pfitter_def
Definition: CscSplitClusterFitter.h:51
CscSplitClusterFitter::initialize
StatusCode initialize()
Definition: CscSplitClusterFitter.cxx:40
python.Dumpers.aname
string aname
Definition: Dumpers.py:5541
UNKNOWN_STATION
@ UNKNOWN_STATION
Definition: ParabolaCscClusterFitter.h:25
Muon::CscStripPrepData
Class representing the raw data of one CSC strip (for clusters look at Muon::CscPrepData).
Definition: CscStripPrepData.h:40
WriteCellNoiseToCool.ival
ival
Definition: WriteCellNoiseToCool.py:337
Muon::CscStatusSplitStripFitFailed
@ CscStatusSplitStripFitFailed
Definition: CscClusterStatus.h:88
Muon::CscStatusSaturated
@ CscStatusSaturated
Definition: CscClusterStatus.h:56
ICscClusterFitter::Result
Definition: ICscClusterFitter.h:52
CscPrepData.h
CscSplitClusterFitter::m_max_qratio
float m_max_qratio
Definition: CscSplitClusterFitter.h:42
Muon::CscStatusStripFitFailed
@ CscStatusStripFitFailed
Definition: CscClusterStatus.h:53
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
Muon::CscPrepData
Class representing clusters from the CSC.
Definition: CscPrepData.h:39
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Muon::CscStatusSplitMultiPeak
@ CscStatusSplitMultiPeak
More than one peak in cluster after split cluster.
Definition: CscClusterStatus.h:71
Muon::CscStatusSimple
@ CscStatusSimple
Cluster with non-precision fit.
Definition: CscClusterStatus.h:29
Muon::CscStatusQratInconsistent
@ CscStatusQratInconsistent
Positions from Qrat_left and Qrat_right is not consistent.
Definition: CscClusterStatus.h:49
ICscClusterFitter::DataNames
std::vector< std::string > DataNames
Definition: ICscClusterFitter.h:46
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:14
CscReadoutElement.h
test_pyathena.parent
parent
Definition: test_pyathena.py:15
Muon::CscStatusSplitEdge
@ CscStatusSplitEdge
Cluster reaches the edge of plane after split cluster.
Definition: CscClusterStatus.h:68
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Muon::CscStatusWide
@ CscStatusWide
Too wide.
Definition: CscClusterStatus.h:43
ICscStripFitter::Result
Definition: ICscStripFitter.h:25
Muon::CscStatusSkewed
@ CscStatusSkewed
Skewed, e.g.
Definition: CscClusterStatus.h:46
Muon::CscStatusUndefined
@ CscStatusUndefined
Undefined, should not happen, most likely indicates a problem.
Definition: CscClusterStatus.h:94
CscClusterStatus.h
CscSplitClusterFitter::m_min_dist
int m_min_dist
Definition: CscSplitClusterFitter.h:40
Trk::PrepRawData::identify
Identifier identify() const
return the identifier
fitman.fitresult
fitresult
Definition: fitman.py:590
Muon::CscStatusNarrow
@ CscStatusNarrow
Too narrow.
Definition: CscClusterStatus.h:40
Muon::CscStatusSplitSaturated
@ CscStatusSplitSaturated
Definition: CscClusterStatus.h:91
Result
Definition: fbtTestBasics.cxx:47
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
CscSplitClusterFitter::CscSplitClusterFitter
CscSplitClusterFitter(const std::string &, const std::string &, const IInterface *)
Definition: CscSplitClusterFitter.cxx:31
charge
double charge(const T &p)
Definition: AtlasPID.h:494
Muon::CscStatusSplitWide
@ CscStatusSplitWide
Too wide.
Definition: CscClusterStatus.h:77
CscSplitClusterFitter::m_pfitter_prec
ToolHandle< ICscClusterFitter > m_pfitter_prec
Definition: CscSplitClusterFitter.h:56
python.ami.results
def results
Definition: ami.py:386
Results
std::vector< Result > Results
Definition: CscSplitClusterFitter.cxx:22
Result
ICscClusterFitter::Result Result
Definition: CscSplitClusterFitter.cxx:21
Muon::CscStatusMultiPeak
@ CscStatusMultiPeak
More than one peak in cluster.
Definition: CscClusterStatus.h:37
Muon::CscStatusSplitQratInconsistent
@ CscStatusSplitQratInconsistent
Positions from Qrat_left and Qrat_right is not consistent after split cluster.
Definition: CscClusterStatus.h:84
Muon::CscStatusSplitUnspoiled
@ CscStatusSplitUnspoiled
Clean cluster with precision fit after split cluster.
Definition: CscClusterStatus.h:59
trigbs_pickEvents.cnt
cnt
Definition: trigbs_pickEvents.py:71
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
CscStation
CscStation
Definition: ParabolaCscClusterFitter.h:25
CscSplitClusterFitter::getCorrectedError
double getCorrectedError(const Muon::CscPrepData *pclu, double slope) const
Definition: CscSplitClusterFitter.cxx:322
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
UNKNOWN_PLANE
@ UNKNOWN_PLANE
Definition: ParabolaCscClusterFitter.h:26
ICscClusterFitter::StripFitList
std::vector< StripFit > StripFitList
Definition: ICscClusterFitter.h:40
Muon::CscClusterStatus
CscClusterStatus
Enum to represent the cluster status - see the specific enum values for more details.
Definition: CscClusterStatus.h:23
AthAlgTool
Definition: AthAlgTool.h:26
CSL
@ CSL
Definition: ParabolaCscClusterFitter.h:25
CscPlane
CscPlane
Definition: ParabolaCscClusterFitter.h:26
CscSplitClusterFitter.h
CSL_PHI
@ CSL_PHI
Definition: ParabolaCscClusterFitter.h:26
Muon::CscStatusEdge
@ CscStatusEdge
Cluster reaches the edge of plane.
Definition: CscClusterStatus.h:34
CscSplitClusterFitter::fit
Results fit(const StripFitList &sfits) const
Definition: CscSplitClusterFitter.cxx:65
CscSplitClusterFitter::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: CscSplitClusterFitter.h:44