CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
HGCalWaferValidation.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Validation/HGCalValidation
4 // Class: HGCalWaferValidation
5 //
20 //
21 // Original Author: Imran Yusuff
22 // Created: Thu, 27 May 2021 19:47:08 GMT
23 //
24 // Modified by: Yulun Miao
25 // Modified at: Wed, 17 Nov 2021 21:04:10 UTC
26 /*
27  Details of Modification:
28  * Use the l or h preceding the thickness to determine the type of flat file
29  * Unified partial wafer information to HGCalTypes.h to allow cross-compare
30 */
31 // system include files
32 #include <memory>
33 
34 // user include files
37 
40 
45 
49 
50 #include <fstream>
51 #include <regex>
52 
53 //
54 // class declaration
55 //
56 
57 // If the analyzer does not use TFileService, please remove
58 // the template argument to the base class so the class inherits
59 // from edm::one::EDAnalyzer<>
60 // This will improve performance in multithreaded jobs.
61 
63 public:
64  explicit HGCalWaferValidation(const edm::ParameterSet&);
65  ~HGCalWaferValidation() override;
66 
67  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
68 
69 private:
70  // This is MessageLogger logging category
71  const std::string logcat = "HGCalWaferValidation";
72 
73  // wafer coordinate is (layer, u, v), used as index for map
74  using WaferCoord = std::tuple<int, int, int>;
75 
76  std::string strWaferCoord(const WaferCoord& coord);
77 
78  bool DDFindHGCal(DDCompactView::GraphWalker& walker, std::string targetName);
81 
82  void beginJob() override;
83  void analyze(const edm::Event&, const edm::EventSetup&) override;
84  void endJob() override;
85 
86  // ----------member data ---------------------------
87  // module parameters
89 
90  // struct to hold wafer information from DD in map
91  struct WaferInfo {
93  double x;
94  double y;
95  int shapeCode;
96  int rotCode;
97  };
98 
99  // EDM token to access DD
101 
102  // map holding all wafer properties from DD
103  std::map<WaferCoord, struct WaferInfo> waferData;
104 
105  // boolean map to keep track of unaccounted DD wafers (not in flat file)
106  std::map<WaferCoord, bool> waferValidated;
107 };
108 
109 //
110 // constants, enums and typedefs
111 //
112 
113 //
114 // static data member definitions
115 //
116 
117 //
118 // constructors and destructor
119 //
121  : geometryFileName_(iConfig.getParameter<edm::FileInPath>("GeometryFileName")) {
122  viewToken_ = esConsumes<DDCompactView, IdealGeometryRecord>();
123  //now do what ever initialization is needed
124 }
125 
127  // do anything here that needs to be done at desctruction time
128  // (e.g. close files, deallocate resources etc.)
129  //
130  // please remove this method altogether if it would be left empty
131 }
132 
133 //
134 // member functions
135 //
136 
137 // convert WaferCoord tuple to string representation (i.e. for printing)
139  std::stringstream ss;
140  ss << "(" << std::get<0>(coord) << "," << std::get<1>(coord) << "," << std::get<2>(coord) << ")";
141  return ss.str();
142 }
143 
144 // ----- find HGCal entry among the DD -----
146  if (walker.current().first.name().name() == targetName) {
147  // target found
148  return true;
149  }
150  if (walker.firstChild()) {
151  do {
152  if (DDFindHGCal(walker, targetName))
153  // target inside child
154  return true;
155  } while (walker.nextSibling());
156  walker.parent();
157  }
158  return false;
159 }
160 
161 // ----- find the next wafer, then process the wafer layer -----
163  if (walker.current().first.name().fullname().rfind("hgcalwafer:", 0) == 0) {
164  // first wafer found. Now process the entire layer of wafers.
165  ProcessWaferLayer(walker);
166  return;
167  }
168  if (walker.firstChild()) {
169  do {
170  DDFindWafers(walker);
171  } while (walker.nextSibling());
172  walker.parent();
173  }
174 }
175 
176 // ----- process the layer of wafers -----
178  static int waferLayer = 0; // layer numbers in DD are assumed to be sequential from 1
179  waferLayer++;
180  edm::LogVerbatim(logcat) << "ProcessWaferLayer: Processing layer " << waferLayer;
181  do {
182  if (walker.current().first.name().fullname().rfind("hgcalwafer:", 0) == 0) {
183  auto wafer = walker.current();
184  const std::string waferName(walker.current().first.name().fullname());
185  const int copyNo = wafer.second->copyno();
186  // extract DD layer properties
187  const int waferType = HGCalTypes::getUnpackedType(copyNo);
188  const int waferU = HGCalTypes::getUnpackedU(copyNo);
189  const int waferV = HGCalTypes::getUnpackedV(copyNo);
190  const WaferCoord waferCoord(waferLayer, waferU, waferV); // map index
191  // build struct of DD wafer properties
192  struct WaferInfo waferInfo;
193  waferInfo.thickClass = waferType;
194  waferInfo.x = wafer.second->translation().x();
195  waferInfo.y = wafer.second->translation().y();
196  const std::string waferNameData =
197  std::regex_replace(waferName,
198  std::regex("(HGCal[EH]E)(Wafer[01])(Fine|Coarse[12])([a-z]*)([0-9]*)"),
199  "$1 $2-$3 $4 $5",
200  std::regex_constants::format_no_copy);
201  std::stringstream ss(waferNameData);
202  std::string EEorHE;
203  std::string typeStr;
204  std::string shapeStr;
205  std::string rotStr;
206  ss >> EEorHE >> typeStr >> shapeStr >> rotStr;
207  // assume rotational symmetry of full-sized wafers
208  if (shapeStr.empty())
209  shapeStr = "F";
210  if (rotStr.empty())
211  rotStr = "0";
212  const int rotCode(std::stoi(rotStr));
213  //edm::LogVerbatim(logcat) << "rotStr " << rotStr << " rotCode " << rotCode;
214 
215  // convert shape code to wafer types defined in HGCalTypes.h
216  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferOut;
217  if (shapeStr == "F")
218  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferFull;
219  else if (shapeStr == "a")
220  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferHalf;
221  else if (shapeStr == "am")
222  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferHalf2;
223  else if (shapeStr == "b")
224  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferFive;
225  else if (shapeStr == "bm")
226  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferFive2;
227  else if (shapeStr == "c")
228  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferThree;
229  else if (shapeStr == "d")
230  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferSemi;
231  else if (shapeStr == "dm")
232  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferSemi2;
233  else if (shapeStr == "g")
234  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferChopTwo;
235  else if (shapeStr == "gm")
236  waferInfo.shapeCode = HGCalTypes::WaferPartialType::WaferChopTwoM;
237 
238  waferInfo.rotCode = rotCode;
239  // populate the map
240  waferData[waferCoord] = waferInfo;
241  waferValidated[waferCoord] = false;
242  }
243  } while (walker.nextSibling());
244 }
245 
246 // ------------ method called for each event ------------
248  using namespace edm;
249 
250  // Get the CMS DD
251  auto viewH = iSetup.getHandle(viewToken_);
252 
253  if (!viewH.isValid()) {
254  edm::LogPrint(logcat) << "Error obtaining geometry handle!";
255  return;
256  }
257 
258  edm::LogVerbatim(logcat) << "Root is : " << viewH->root();
259  edm::LogVerbatim(logcat) << std::endl;
260 
261  // find HGCalEE
262  auto eeWalker = viewH->walker();
263  const bool eeFound = DDFindHGCal(eeWalker, "HGCalEE");
264  if (eeFound) {
265  edm::LogVerbatim(logcat) << "HGCalEE found!";
266  edm::LogVerbatim(logcat) << "name = " << eeWalker.current().first.name().name();
267  edm::LogVerbatim(logcat) << "fullname = " << eeWalker.current().first.name().fullname();
268  } else {
269  edm::LogPrint(logcat) << "HGCalEE not found!";
270  }
271  edm::LogVerbatim(logcat) << std::endl;
272 
273  // find HGCalHEsil
274  auto hesilWalker = viewH->walker();
275  const bool hesilFound = DDFindHGCal(hesilWalker, "HGCalHEsil");
276  if (hesilFound) {
277  edm::LogVerbatim(logcat) << "HGCalHEsil found!";
278  edm::LogVerbatim(logcat) << "name = " << hesilWalker.current().first.name().name();
279  edm::LogVerbatim(logcat) << "fullname = " << hesilWalker.current().first.name().fullname();
280  } else {
281  edm::LogPrint(logcat) << "HGCalHEsil not found!";
282  }
283  edm::LogVerbatim(logcat) << std::endl;
284 
285  // find HGCalHEmix
286  auto hemixWalker = viewH->walker();
287  const bool hemixFound = DDFindHGCal(hemixWalker, "HGCalHEmix");
288  if (hemixFound) {
289  edm::LogVerbatim(logcat) << "HGCalHEmix found!";
290  edm::LogVerbatim(logcat) << "name = " << hemixWalker.current().first.name().name();
291  edm::LogVerbatim(logcat) << "fullname = " << hemixWalker.current().first.name().fullname();
292  } else {
293  edm::LogPrint(logcat) << "HGCalHEmix not found!";
294  }
295  edm::LogVerbatim(logcat) << std::endl;
296 
297  // give up if no HGCal found at all
298  if (!(eeFound || hesilFound || hemixFound)) {
299  edm::LogPrint(logcat) << "Nothing found. Giving up.";
300  return;
301  }
302 
303  // Now walk the HGCalEE walker to find the first wafer on each layer and process them
304  edm::LogVerbatim(logcat) << "Calling DDFindWafers(eeWalker);";
305  DDFindWafers(eeWalker);
306 
307  // Walk the HGCalHEsilwalker to find the first wafer on each layer and process them
308  edm::LogVerbatim(logcat) << "Calling DDFindWafers(hesilWalker);";
309  DDFindWafers(hesilWalker);
310 
311  // Walk the HGCalHEmix walker to find the first wafer on each layer and process them
312  edm::LogVerbatim(logcat) << "Calling DDFindWafers(hemixWalker);";
313  DDFindWafers(hemixWalker);
314 
315  // Confirm all the DD wafers have been read
316  edm::LogVerbatim(logcat) << "Number of wafers read from DD: " << waferData.size();
317 
318  // Now open the geometry text file
320  edm::LogVerbatim(logcat) << "Opening geometry text file: " << fileName;
321  std::ifstream geoTxtFile(fileName);
322 
323  if (!geoTxtFile) {
324  edm::LogPrint(logcat) << "Cannot open geometry text file.";
325  return;
326  }
327 
328  // total processed counter
329  int nTotalProcessed = 0;
330 
331  // geometry error counters
332  int nMissing = 0;
333  int nThicknessError = 0;
334  int nPosXError = 0;
335  int nPosYError = 0;
336  int nShapeError = 0;
337  int nRotError = 0;
338  int nUnaccounted = 0;
339 
341 
342  // process each line on the text file
343  while (std::getline(geoTxtFile, buf)) {
344  std::stringstream ss(buf);
345  std::vector<std::string> tokens;
346  while (ss >> buf)
347  if (!buf.empty())
348  tokens.push_back(buf);
349  if (tokens.size() != 8)
350  continue;
351 
352  nTotalProcessed++;
353 
354  int waferLayer;
355  std::string waferShapeStr;
356  std::string waferDensityStr;
357  int waferThickness;
358  double waferX;
359  double waferY;
360  int waferRotCode;
361  int waferU;
362  int waferV;
363  int waferShapeCode;
364  // extract wafer info from a textfile line
365  if (tokens[2].substr(0, 1) == "l" || tokens[2].substr(0, 1) == "h") {
366  //if using new format flat file
367  waferLayer = std::stoi(tokens[0]);
368  waferShapeStr = tokens[1];
369  waferDensityStr = tokens[2].substr(0, 1);
370  waferThickness = std::stoi(tokens[2].substr(1));
371  waferX = std::stod(tokens[3]);
372  waferY = std::stod(tokens[4]);
373  waferRotCode = std::stoi(tokens[5]);
374  waferU = std::stoi(tokens[6]);
375  waferV = std::stoi(tokens[7]);
376  waferShapeCode = HGCalTypes::WaferPartialType::WaferOut;
377  if (waferDensityStr == "l") {
378  if (waferShapeStr == "0")
379  waferShapeCode = HGCalTypes::WaferPartialType::WaferFull;
380  else if (waferShapeStr == "1" || waferShapeStr == "2")
381  waferShapeCode = HGCalTypes::WaferPartialType::WaferHalf;
382  else if (waferShapeStr == "3" || waferShapeStr == "4")
383  waferShapeCode = HGCalTypes::WaferPartialType::WaferSemi;
384  else if (waferShapeStr == "5")
385  waferShapeCode = HGCalTypes::WaferPartialType::WaferFive;
386  else if (waferShapeStr == "6")
387  waferShapeCode = HGCalTypes::WaferPartialType::WaferThree;
388  } else if (waferDensityStr == "h") {
389  if (waferShapeStr == "0")
390  waferShapeCode = HGCalTypes::WaferPartialType::WaferFull;
391  else if (waferShapeStr == "1")
392  waferShapeCode = HGCalTypes::WaferPartialType::WaferHalf2;
393  else if (waferShapeStr == "2")
394  waferShapeCode = HGCalTypes::WaferPartialType::WaferChopTwoM;
395  else if (waferShapeStr == "3" || waferShapeStr == "4")
396  waferShapeCode = HGCalTypes::WaferPartialType::WaferSemi2;
397  else if (waferShapeStr == "5")
398  waferShapeCode = HGCalTypes::WaferPartialType::WaferFive2;
399  }
400  } else {
401  //if using old format flat file
402  waferLayer = std::stoi(tokens[0]);
403  waferShapeStr = tokens[1];
404  waferThickness = std::stoi(tokens[2]);
405  waferX = std::stod(tokens[3]);
406  waferY = std::stod(tokens[4]);
407  waferRotCode = (std::stoi(tokens[5]));
408  waferU = std::stoi(tokens[6]);
409  waferV = std::stoi(tokens[7]);
410  waferShapeCode = HGCalTypes::WaferPartialType::WaferOut;
411  if (waferShapeStr == "F")
412  waferShapeCode = HGCalTypes::WaferPartialType::WaferFull;
413  else if (waferShapeStr == "a")
414  waferShapeCode = HGCalTypes::WaferPartialType::WaferHalf;
415  else if (waferShapeStr == "am")
416  waferShapeCode = HGCalTypes::WaferPartialType::WaferHalf2;
417  else if (waferShapeStr == "b")
418  waferShapeCode = HGCalTypes::WaferPartialType::WaferFive;
419  else if (waferShapeStr == "bm")
420  waferShapeCode = HGCalTypes::WaferPartialType::WaferFive2;
421  else if (waferShapeStr == "c")
422  waferShapeCode = HGCalTypes::WaferPartialType::WaferThree;
423  else if (waferShapeStr == "d")
424  waferShapeCode = HGCalTypes::WaferPartialType::WaferSemi;
425  else if (waferShapeStr == "dm")
426  waferShapeCode = HGCalTypes::WaferPartialType::WaferSemi2;
427  else if (waferShapeStr == "g")
428  waferShapeCode = HGCalTypes::WaferPartialType::WaferChopTwo;
429  else if (waferShapeStr == "gm")
430  waferShapeCode = HGCalTypes::WaferPartialType::WaferChopTwoM;
431  }
432 
433  // map index for crosschecking with DD
434  const WaferCoord waferCoord(waferLayer, waferU, waferV);
435 
436  // now check for (and report) wafer data disagreements
437 
438  if (waferData.find(waferCoord) == waferData.end()) {
439  nMissing++;
440  edm::LogVerbatim(logcat) << "MISSING: " << strWaferCoord(waferCoord);
441  continue;
442  }
443 
444  const struct WaferInfo waferInfo = waferData[waferCoord];
445  waferValidated[waferCoord] = true;
446 
447  if ((waferInfo.thickClass == 0 && waferThickness != 120) || (waferInfo.thickClass == 1 && waferThickness != 200) ||
448  (waferInfo.thickClass == 2 && waferThickness != 300)) {
449  nThicknessError++;
450  edm::LogVerbatim(logcat) << "THICKNESS ERROR: " << strWaferCoord(waferCoord);
451  }
452 
453  // it seems that wafer x-coords relative to their layer plane are mirrored...
454  if (fabs(-waferInfo.x - waferX) > 0.015) { // assuming this much tolerance
455  nPosXError++;
456  edm::LogVerbatim(logcat) << "POSITION x ERROR: " << strWaferCoord(waferCoord);
457  }
458 
459  if (fabs(waferInfo.y - waferY) > 0.015) { // assuming this much tolerance
460  nPosYError++;
461  edm::LogVerbatim(logcat) << "POSITION y ERROR: " << strWaferCoord(waferCoord);
462  }
463 
464  if (waferInfo.shapeCode != waferShapeCode || waferShapeCode == HGCalTypes::WaferPartialType::WaferOut) {
465  nShapeError++;
466  edm::LogVerbatim(logcat) << "SHAPE ERROR: " << strWaferCoord(waferCoord);
467  }
468 
469  if ((waferShapeCode != HGCalTypes::WaferPartialType::WaferFull && waferInfo.rotCode != waferRotCode) ||
470  (waferShapeCode == HGCalTypes::WaferPartialType::WaferFull && (waferInfo.rotCode % 2 != waferRotCode % 2))) {
471  nRotError++;
472  edm::LogVerbatim(logcat) << "ROTATION ERROR: " << strWaferCoord(waferCoord) << " ( " << waferInfo.rotCode
473  << " != " << waferRotCode << " )";
474  }
475  }
476 
477  geoTxtFile.close();
478 
479  // Find unaccounted DD wafers
480  for (auto const& accounted : waferValidated) {
481  if (!accounted.second) {
482  nUnaccounted++;
483  edm::LogVerbatim(logcat) << "UNACCOUNTED: " << strWaferCoord(accounted.first);
484  }
485  }
486 
487  // Print out error counts
488  edm::LogVerbatim(logcat) << std::endl;
489  edm::LogVerbatim(logcat) << "*** ERROR COUNTS ***";
490  edm::LogVerbatim(logcat) << "Missing : " << nMissing;
491  edm::LogVerbatim(logcat) << "Thickness error : " << nThicknessError;
492  edm::LogVerbatim(logcat) << "Pos-x error : " << nPosXError;
493  edm::LogVerbatim(logcat) << "Pos-y error : " << nPosYError;
494  edm::LogVerbatim(logcat) << "Shape error : " << nShapeError;
495  edm::LogVerbatim(logcat) << "Rotation error : " << nRotError;
496  edm::LogVerbatim(logcat) << "Unaccounted : " << nUnaccounted;
497  edm::LogVerbatim(logcat) << std::endl;
498  edm::LogVerbatim(logcat) << "Total wafers processed from geotxtfile = " << nTotalProcessed;
499  edm::LogVerbatim(logcat) << std::endl;
500 
501  // Issue a LogPrint (warning) if there is at least one wafer errors
502  if (nMissing > 0 || nThicknessError > 0 || nPosXError > 0 || nPosYError > 0 || nShapeError > 0 || nRotError > 0 ||
503  nUnaccounted > 0) {
504  edm::LogPrint(logcat) << "There are at least one wafer error.";
505  }
506 }
507 
508 // ------------ method called once each job just before starting event loop ------------
510  // please remove this method if not needed
511 }
512 
513 // ------------ method called once each job just after ending the event loop ------------
515  // please remove this method if not needed
516 }
517 
518 // ------------ method fills 'descriptions' with the allowed parameters for the module ------------
520  //The following says we do not know what parameters are allowed so do no validation
521  // Please change this to state exactly what you do use, even if it is no parameters
523  desc.add<edm::FileInPath>("GeometryFileName",
524  edm::FileInPath("Validation/HGCalValidation/data/geomnew_corrected_360.txt"));
525  descriptions.add("hgcalWaferValidation", desc);
526 }
527 
528 //define this as a plug-in
Log< level::Info, true > LogVerbatim
void ProcessWaferLayer(DDCompactView::GraphWalker &walker)
bool DDFindHGCal(DDCompactView::GraphWalker &walker, std::string targetName)
static int32_t getUnpackedU(int id)
Definition: HGCalTypes.cc:16
int32_t waferU(const int32_t index)
int32_t waferLayer(const int32_t index)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
const std::string logcat
static int32_t getUnpackedV(int id)
Definition: HGCalTypes.cc:22
std::tuple< int, int, int > WaferCoord
int iEvent
Definition: GenABIO.cc:224
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
result_type parent()
Definition: GraphWalker.h:130
void analyze(const edm::Event &, const edm::EventSetup &) override
static int32_t getUnpackedType(int id)
Definition: HGCalTypes.cc:14
result_type firstChild()
Definition: GraphWalker.h:108
ParameterDescriptionBase * add(U const &iLabel, T const &value)
Log< level::Warning, true > LogPrint
result_type nextSibling()
Definition: GraphWalker.h:119
edm::ESGetToken< DDCompactView, IdealGeometryRecord > viewToken_
void add(std::string const &label, ParameterSetDescription const &psetDescription)
std::map< WaferCoord, bool > waferValidated
std::string strWaferCoord(const WaferCoord &coord)
int32_t waferV(const int32_t index)
std::string fullPath() const
Definition: FileInPath.cc:161
edm::FileInPath geometryFileName_
void DDFindWafers(DDCompactView::GraphWalker &walker)
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:157
HGCalWaferValidation(const edm::ParameterSet &)
std::map< WaferCoord, struct WaferInfo > waferData
value_type current() const
Definition: GraphWalker.h:86