Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:37:22

0001 /****************************************************************************
0002  *
0003  * This is a part of CMS-TOTEM PPS offline software.
0004  * Authors:
0005  * Jan Kaspar
0006  * Helena Malbouisson
0007  * Clemencia Mora Herrera
0008  *
0009  ****************************************************************************/
0010 
0011 #include "CondFormats/PPSObjects/interface/CTPPSRPAlignmentCorrectionsMethods.h"
0012 
0013 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0014 #include "FWCore/Utilities/interface/typelookup.h"
0015 #include "FWCore/Utilities/interface/Exception.h"
0016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0017 
0018 #include "DataFormats/CTPPSDetId/interface/CTPPSDetId.h"
0019 #include "DataFormats/CTPPSDetId/interface/TotemRPDetId.h"
0020 #include "DataFormats/CTPPSDetId/interface/CTPPSPixelDetId.h"
0021 #include "DataFormats/CTPPSDetId/interface/CTPPSDiamondDetId.h"
0022 
0023 #include "Utilities/Xerces/interface/XercesStrUtils.h"
0024 
0025 #include <xercesc/parsers/XercesDOMParser.hpp>
0026 #include <xercesc/sax/HandlerBase.hpp>
0027 #include <xercesc/util/XMLString.hpp>
0028 #include <xercesc/util/PlatformUtils.hpp>
0029 
0030 #include <map>
0031 #include <set>
0032 
0033 #ifdef XERCES_CPP_NAMESPACE_USE
0034 XERCES_CPP_NAMESPACE_USE
0035 #endif
0036 
0037 //----------------------------------------------------------------------------------------------------
0038 
0039 /**
0040 STRUCTURE OF CTPPS ALINGMENT XML FILE
0041 The file has the following structure
0042 <code>
0043 <xml>
0044   <iov first="run:ls" last="run:ls">
0045     <tag/>
0046     <tag/>
0047     ...
0048   </iov>
0049   <iov first="run:ls" last="run:ls">
0050     ...
0051   </iov>
0052   .
0053   .
0054   .
0055 </xml>
0056 </code>
0057 The time intervals are specified by the `first' and `last' run-lumisection pairs.
0058 If the <iov> tag is not present, an infinite validty is assumed for all the tags.
0059 The tag can be either
0060 * "det" - the alignment correction is applied to one detector or
0061 * "rp" - the alignment correction id applied to one RP
0062 Each tag must have an "id" attribute set. In addition the following attributes are recognized:
0063 * sh_x - shift in x
0064 * sh_x_e - the uncertainty of sh_x determination
0065 * sh_y - shift in y
0066 * sh_y_e - the uncertainty of sh_y determination
0067 * sh_z - shift in z
0068 * sh_z_e - the uncertainty of sh_z determination
0069 * rot_x - rotation around x
0070 * rot_x_e - the uncertainty of rot_x determination
0071 * rot_y - rotation around y
0072 * rot_y_e - the uncertainty of rot_y determination
0073 * rot_z - rotation around z
0074 * rot_z_e - the uncertainty of rot_z determination
0075 UNITS: shifts are in um, rotations are in mrad.
0076 */
0077 
0078 //----------------------------------------------------------------------------------------------------
0079 edm::IOVSyncValue CTPPSRPAlignmentCorrectionsMethods::stringToIOVValue(const std::string& str) {
0080   if (str == "-inf")
0081     return edm::IOVSyncValue::beginOfTime();
0082 
0083   if (str == "+inf")
0084     return edm::IOVSyncValue::endOfTime();
0085 
0086   size_t sep_pos = str.find(':');
0087   const std::string& runStr = str.substr(0, sep_pos);
0088   const std::string& lsStr = str.substr(sep_pos + 1);
0089 
0090   return edm::IOVSyncValue(edm::EventID(atoi(runStr.c_str()), atoi(lsStr.c_str()), 1));
0091 }
0092 
0093 //----------------------------------------------------------------------------------------------------
0094 
0095 std::string CTPPSRPAlignmentCorrectionsMethods::iovValueToString(const edm::IOVSyncValue& val) {
0096   if (val == edm::IOVSyncValue::beginOfTime())
0097     return "-inf";
0098 
0099   if (val == edm::IOVSyncValue::endOfTime())
0100     return "+inf";
0101 
0102   char buf[50];
0103   sprintf(buf, "%u:%u", val.eventID().run(), val.eventID().luminosityBlock());
0104   return buf;
0105 }
0106 
0107 //----------------------------------------------------------------------------------------------------
0108 
0109 CTPPSRPAlignmentCorrectionsDataSequence CTPPSRPAlignmentCorrectionsMethods::loadFromXML(const std::string& fileName) {
0110   // prepare output
0111   CTPPSRPAlignmentCorrectionsDataSequence output;
0112 
0113   // load DOM tree
0114   try {
0115     XMLPlatformUtils::Initialize();
0116   } catch (const XMLException& toCatch) {
0117     throw cms::Exception("CTPPSRPAlignmentCorrectionsMethods")
0118         << "An XMLException caught with message: " << cms::xerces::toString(toCatch.getMessage()) << ".";
0119   }
0120 
0121   auto parser = std::make_unique<XercesDOMParser>();
0122   parser->setValidationScheme(XercesDOMParser::Val_Always);
0123   parser->setDoNamespaces(true);
0124   parser->parse(fileName.c_str());
0125 
0126   if (!parser)
0127     throw cms::Exception("CTPPSRPAlignmentCorrectionsMethods")
0128         << "Cannot parse file `" << fileName << "' (parser = NULL).";
0129 
0130   DOMDocument* xmlDoc = parser->getDocument();
0131 
0132   if (!xmlDoc)
0133     throw cms::Exception("CTPPSRPAlignmentCorrectionsMethods")
0134         << "Cannot parse file `" << fileName << "' (xmlDoc = NULL).";
0135 
0136   DOMElement* elementRoot = xmlDoc->getDocumentElement();
0137   if (!elementRoot)
0138     throw cms::Exception("CTPPSRPAlignmentCorrectionsMethods") << "File `" << fileName << "' is empty.";
0139 
0140   // extract useful information form the DOM tree
0141   DOMNodeList* children = elementRoot->getChildNodes();
0142   for (unsigned int i = 0; i < children->getLength(); i++) {
0143     DOMNode* node = children->item(i);
0144     if (node->getNodeType() != DOMNode::ELEMENT_NODE)
0145       continue;
0146 
0147     const std::string node_name = cms::xerces::toString(node->getNodeName());
0148 
0149     // check node type
0150     unsigned char nodeType = 0;
0151     if (node_name == "iov")
0152       nodeType = 1;
0153     else if (node_name == "det")
0154       nodeType = 2;
0155     else if (node_name == "rp")
0156       nodeType = 3;
0157 
0158     if (nodeType == 0)
0159       throw cms::Exception("CTPPSRPAlignmentCorrectionsMethods") << "Unknown node `" << node_name << "'.";
0160 
0161     // for backward compatibility: support files with no iov block
0162     if (nodeType == 2 || nodeType == 3) {
0163       const edm::ValidityInterval iov(edm::IOVSyncValue::beginOfTime(), edm::IOVSyncValue::endOfTime());
0164       output.insert(iov, getCorrectionsData(elementRoot));
0165       break;
0166     }
0167 
0168     // get attributes
0169     edm::IOVSyncValue first, last;
0170     bool first_set = false, last_set = false;
0171     DOMNamedNodeMap* attrs = node->getAttributes();
0172     for (unsigned int j = 0; j < attrs->getLength(); j++) {
0173       const DOMNode* attr = attrs->item(j);
0174       const std::string attr_name = cms::xerces::toString(attr->getNodeName());
0175 
0176       if (attr_name == "first") {
0177         first_set = true;
0178         first = stringToIOVValue(cms::xerces::toString(attr->getNodeValue()));
0179       } else if (attr_name == "last") {
0180         last_set = true;
0181         last = stringToIOVValue(cms::xerces::toString(attr->getNodeValue()));
0182       } else
0183         edm::LogProblem("CTPPSRPAlignmentCorrectionsMethods")
0184             << ">> CTPPSRPAlignmentCorrectionsDataSequence::loadFromXML > Warning: unknown attribute `" << attr_name
0185             << "'.";
0186     }
0187 
0188     // interval of validity must be set
0189     if (!first_set || !last_set)
0190       throw cms::Exception("CTPPSRPAlignmentCorrectionsMethods")
0191           << "iov tag must have `first' and `last' attributes set.";
0192 
0193     // process data
0194     CTPPSRPAlignmentCorrectionsData corrections = CTPPSRPAlignmentCorrectionsMethods::getCorrectionsData(node);
0195 
0196     // save result
0197     output.insert(edm::ValidityInterval(first, last), corrections);
0198   }
0199 
0200   // clean up
0201   parser.reset();
0202   XMLPlatformUtils::Terminate();
0203 
0204   return output;
0205 }
0206 
0207 //----------------------------------------------------------------------------------------------------
0208 
0209 CTPPSRPAlignmentCorrectionsData CTPPSRPAlignmentCorrectionsMethods::getCorrectionsData(DOMNode* root) {
0210   CTPPSRPAlignmentCorrectionsData result;
0211 
0212   DOMNodeList* children = root->getChildNodes();
0213   for (unsigned int i = 0; i < children->getLength(); i++) {
0214     DOMNode* node = children->item(i);
0215     if (node->getNodeType() != DOMNode::ELEMENT_NODE)
0216       continue;
0217 
0218     const std::string node_name = cms::xerces::toString(node->getNodeName());
0219 
0220     // check node type
0221     unsigned char nodeType = 0;
0222     if (node_name == "det")
0223       nodeType = 1;
0224     else if (node_name == "rp")
0225       nodeType = 2;
0226 
0227     if (nodeType == 0)
0228       throw cms::Exception("CTPPSRPAlignmentCorrectionsMethods")
0229           << "Unknown node `" << cms::xerces::toString(node->getNodeName()) << "'.";
0230 
0231     // check children
0232     if (node->getChildNodes()->getLength() > 0) {
0233       edm::LogProblem("CTPPSRPAlignmentCorrectionsMethods")
0234           << "LoadXMLFile > Warning: tag `" << cms::xerces::toString(node->getNodeName()) << "' has "
0235           << node->getChildNodes()->getLength() << " children nodes - they will be all ignored.";
0236     }
0237 
0238     // default values
0239     double sh_x = 0., sh_y = 0., sh_z = 0., rot_x = 0., rot_y = 0., rot_z = 0.;
0240     double sh_x_e = 0., sh_y_e = 0., sh_z_e = 0., rot_x_e = 0., rot_y_e = 0., rot_z_e = 0.;
0241     unsigned int id = 0;
0242     bool idSet = false;
0243 
0244     // get attributes
0245     DOMNamedNodeMap* attr = node->getAttributes();
0246     for (unsigned int j = 0; j < attr->getLength(); j++) {
0247       DOMNode* a = attr->item(j);
0248       const std::string node_name = cms::xerces::toString(a->getNodeName());
0249 
0250       if (node_name == "id") {
0251         id = cms::xerces::toUInt(a->getNodeValue());
0252         idSet = true;
0253       } else if (node_name == "sh_x")
0254         sh_x = cms::xerces::toDouble(a->getNodeValue());
0255       else if (node_name == "sh_x_e")
0256         sh_x_e = cms::xerces::toDouble(a->getNodeValue());
0257       else if (node_name == "sh_y")
0258         sh_y = cms::xerces::toDouble(a->getNodeValue());
0259       else if (node_name == "sh_y_e")
0260         sh_y_e = cms::xerces::toDouble(a->getNodeValue());
0261       else if (node_name == "sh_z")
0262         sh_z = cms::xerces::toDouble(a->getNodeValue());
0263       else if (node_name == "sh_z_e")
0264         sh_z_e = cms::xerces::toDouble(a->getNodeValue());
0265       else if (node_name == "rot_x")
0266         rot_x = cms::xerces::toDouble(a->getNodeValue());
0267       else if (node_name == "rot_x_e")
0268         rot_x_e = cms::xerces::toDouble(a->getNodeValue());
0269       else if (node_name == "rot_y")
0270         rot_y = cms::xerces::toDouble(a->getNodeValue());
0271       else if (node_name == "rot_y_e")
0272         rot_y_e = cms::xerces::toDouble(a->getNodeValue());
0273       else if (node_name == "rot_z")
0274         rot_z = cms::xerces::toDouble(a->getNodeValue());
0275       else if (node_name == "rot_z_e")
0276         rot_z_e = cms::xerces::toDouble(a->getNodeValue());
0277       else
0278         edm::LogProblem("CTPPSRPAlignmentCorrectionsMethods")
0279             << ">> CTPPSRPAlignmentCorrectionsMethods::getCorrectionsData > Warning: unknown attribute `"
0280             << cms::xerces::toString(a->getNodeName()) << "'.";
0281     }
0282 
0283     // id must be set
0284     if (!idSet)
0285       throw cms::Exception("CTPPSRPAlignmentCorrectionsMethods")
0286           << "Id not set for tag `" << cms::xerces::toString(node->getNodeName()) << "'.";
0287 
0288     // build alignment
0289     const CTPPSRPAlignmentCorrectionData align_corr(sh_x * 1e-3,
0290                                                     sh_x_e * 1e-3,
0291                                                     sh_y * 1e-3,
0292                                                     sh_y_e * 1e-3,
0293                                                     sh_z * 1e-3,
0294                                                     sh_z_e * 1e-3,
0295                                                     rot_x * 1e-3,
0296                                                     rot_x_e * 1e-3,
0297                                                     rot_y * 1e-3,
0298                                                     rot_y_e * 1e-3,
0299                                                     rot_z * 1e-3,
0300                                                     rot_z_e * 1e-3);
0301 
0302     // add the alignment to the right list
0303     if (nodeType == 1)
0304       result.addSensorCorrection(id, align_corr, true);
0305     if (nodeType == 2)
0306       result.addRPCorrection(id, align_corr, true);
0307   }
0308 
0309   return result;
0310 }
0311 
0312 //----------------------------------------------------------------------------------------------------
0313 //----------------------------------------------------------------------------------------------------
0314 
0315 void CTPPSRPAlignmentCorrectionsMethods::writeToXML(const CTPPSRPAlignmentCorrectionsDataSequence& data,
0316                                                     const std::string& fileName,
0317                                                     bool precise,
0318                                                     bool wrErrors,
0319                                                     bool wrSh_xy,
0320                                                     bool wrSh_z,
0321                                                     bool wrRot_xy,
0322                                                     bool wrRot_z) {
0323   FILE* rf = fopen(fileName.c_str(), "w");
0324   if (!rf)
0325     throw cms::Exception("CTPPSRPAlignmentCorrectionsMethods")
0326         << "Cannot open file `" << fileName << "' to save alignments.";
0327 
0328   fprintf(rf, "<!-- Shifts in um, rotations in mrad. -->\n");
0329   fprintf(rf, "<xml DocumentType=\"AlignmentDescription\">\n");
0330 
0331   // write all IOVs
0332   for (const auto& p : data) {
0333     fprintf(rf,
0334             "\t<iov first=\"%s\" last=\"%s\">\n",
0335             iovValueToString(p.first.first()).c_str(),
0336             iovValueToString(p.first.last()).c_str());
0337 
0338     writeXMLBlock(p.second, rf, precise, wrErrors, wrSh_xy, wrSh_z, wrRot_xy, wrRot_z);
0339 
0340     fprintf(rf, "\t</iov>\n");
0341   }
0342 
0343   fprintf(rf, "</xml>\n");
0344   fclose(rf);
0345 }
0346 
0347 void CTPPSRPAlignmentCorrectionsMethods::writeXMLBlock(const CTPPSRPAlignmentCorrectionsData& data,
0348                                                        FILE* rf,
0349                                                        bool precise,
0350                                                        bool wrErrors,
0351                                                        bool wrSh_xy,
0352                                                        bool wrSh_z,
0353                                                        bool wrRot_xy,
0354                                                        bool wrRot_z) {
0355   bool firstRP = true;
0356   unsigned int prevRP = 0;
0357   std::set<unsigned int> writtenRPs;
0358 
0359   const auto& sensors = data.getSensorMap();
0360   const auto& rps = data.getRPMap();
0361 
0362   for (auto it = sensors.begin(); it != sensors.end(); ++it) {
0363     CTPPSDetId sensorId(it->first);
0364     unsigned int rpId = sensorId.rpId();
0365     unsigned int decRPId = sensorId.arm() * 100 + sensorId.station() * 10 + sensorId.rp();
0366 
0367     // start a RP block
0368     if (firstRP || prevRP != rpId) {
0369       if (!firstRP)
0370         fprintf(rf, "\n");
0371       firstRP = false;
0372 
0373       fprintf(rf, "\t<!-- RP %3u -->\n", decRPId);
0374 
0375       auto rit = rps.find(rpId);
0376       if (rit != rps.end()) {
0377         fprintf(rf, "\t<rp id=\"%u\"                  ", rit->first);
0378         writeXML(rit->second, rf, precise, wrErrors, wrSh_xy, wrSh_z, wrRot_xy, wrRot_z);
0379         fprintf(rf, "/>\n");
0380         writtenRPs.insert(rpId);
0381       }
0382     }
0383     prevRP = rpId;
0384 
0385     // write plane id
0386     unsigned int planeIdx = 1000;
0387     if (sensorId.subdetId() == CTPPSDetId::sdTrackingStrip)
0388       planeIdx = TotemRPDetId(it->first).plane();
0389     if (sensorId.subdetId() == CTPPSDetId::sdTrackingPixel)
0390       planeIdx = CTPPSPixelDetId(it->first).plane();
0391     if (sensorId.subdetId() == CTPPSDetId::sdTimingDiamond)
0392       planeIdx = CTPPSDiamondDetId(it->first).plane();
0393     fprintf(rf, "\t<!-- plane %u --> ", planeIdx);
0394 
0395     // write the correction
0396     fprintf(rf, "<det id=\"%u\"", it->first);
0397     writeXML(it->second, rf, precise, wrErrors, wrSh_xy, wrSh_z, wrRot_xy, wrRot_z);
0398     fprintf(rf, "/>\n");
0399   }
0400 
0401   // write remaining RPs
0402   for (auto it = rps.begin(); it != rps.end(); ++it) {
0403     std::set<unsigned int>::iterator wit = writtenRPs.find(it->first);
0404     if (wit == writtenRPs.end()) {
0405       CTPPSDetId rpId(it->first);
0406       unsigned int decRPId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
0407 
0408       if (!firstRP)
0409         fprintf(rf, "\n");
0410       firstRP = false;
0411 
0412       fprintf(rf, "\t<!-- RP %3u -->\n", decRPId);
0413 
0414       fprintf(rf, "\t<rp id=\"%u\"                  ", it->first);
0415       writeXML(it->second, rf, precise, wrErrors, wrSh_xy, wrSh_z, wrRot_xy, wrRot_z);
0416       fprintf(rf, "/>\n");
0417     }
0418   }
0419 }
0420 
0421 //----------------------------------------------------------------------------------------------------
0422 
0423 #define WRITE(q, tag, dig, lim)                 \
0424   if (precise)                                  \
0425     fprintf(f, " " tag "=\"%.15E\"", q * 1E3);  \
0426   else if (fabs(q * 1E3) < lim && q != 0)       \
0427     fprintf(f, " " tag "=\"%+8.1E\"", q * 1E3); \
0428   else                                          \
0429     fprintf(f, " " tag "=\"%+8." #dig "f\"", q * 1E3);
0430 
0431 //----------------------------------------------------------------------------------------------------
0432 
0433 void CTPPSRPAlignmentCorrectionsMethods::writeXML(const CTPPSRPAlignmentCorrectionData& data,
0434                                                   FILE* f,
0435                                                   bool precise,
0436                                                   bool wrErrors,
0437                                                   bool wrSh_xy,
0438                                                   bool wrSh_z,
0439                                                   bool wrRot_xy,
0440                                                   bool wrRot_z) {
0441   if (wrSh_xy) {
0442     WRITE(data.getShX(), "sh_x", 2, 0.1);
0443     WRITE(data.getShY(), "sh_y", 2, 0.1);
0444     if (wrErrors) {
0445       WRITE(data.getShXUnc(), "sh_x_e", 2, 0.1);
0446       WRITE(data.getShYUnc(), "sh_y_e", 2, 0.1);
0447     }
0448   }
0449 
0450   if (wrSh_z) {
0451     WRITE(data.getShZ(), "sh_z", 2, 0.1);
0452     if (wrErrors) {
0453       WRITE(data.getShZUnc(), "sh_z_e", 2, 0.1);
0454     }
0455   }
0456 
0457   if (wrRot_xy) {
0458     WRITE(data.getRotX(), "rot_x", 3, 0.01);
0459     WRITE(data.getRotY(), "rot_y", 3, 0.01);
0460     if (wrErrors) {
0461       WRITE(data.getRotXUnc(), "rot_x_e", 3, 0.01);
0462       WRITE(data.getRotYUnc(), "rot_y_e", 3, 0.01);
0463     }
0464   }
0465 
0466   if (wrRot_z) {
0467     WRITE(data.getRotZ(), "rot_z", 3, 0.01);
0468     if (wrErrors) {
0469       WRITE(data.getRotZUnc(), "rot_z_e", 3, 0.01);
0470     }
0471   }
0472 }