CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/Alignment/MillePedeAlignmentAlgorithm/src/PedeReader.cc

Go to the documentation of this file.
00001 
00011 #include "PedeReader.h"
00012 #include "PedeSteerer.h"
00013 
00014 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00015 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00016 
00017 #include "Alignment/CommonAlignment/interface/Alignable.h"
00018 #include "Alignment/CommonAlignment/interface/AlignmentParameters.h"
00019 
00020 #include "Alignment/CommonAlignmentAlgorithm/interface/IntegratedCalibrationBase.h"
00021 
00022 #include "Alignment/CommonAlignmentParametrization/interface/RigidBodyAlignmentParameters.h"
00023 
00024 #include "Alignment/MillePedeAlignmentAlgorithm/interface/MillePedeVariables.h"
00025 
00026 #include <set>
00027 #include <string>
00028 #include <sstream>
00029 
00030 const unsigned int PedeReader::myMaxNumValPerParam = 5;
00031 
00032 //__________________________________________________________________________________________________
00033 PedeReader::PedeReader(const edm::ParameterSet &config, const PedeSteerer &steerer,
00034                        const PedeLabelerBase &labels, const RunRange &runrange)
00035   : mySteerer(steerer), myLabels(labels), myRunRange(runrange)
00036 {
00037   std::string pedeResultFile(config.getUntrackedParameter<std::string>("fileDir"));
00038   if (pedeResultFile.empty()) pedeResultFile = steerer.directory(); // includes final '/'
00039   else if (pedeResultFile.find_last_of('/') != pedeResultFile.size() - 1) {
00040     pedeResultFile += '/'; // directory may need '/'
00041   }
00042 
00043   pedeResultFile += config.getParameter<std::string>("readFile");
00044   myPedeResult.open(pedeResultFile.c_str(), std::ios::in);
00045   if (!myPedeResult.is_open()) {
00046     edm::LogError("Alignment") << "@SUB=PedeReader"
00047                                << "Problem opening pede output file " << pedeResultFile;
00048   }
00049 }
00050 
00051 //__________________________________________________________________________________________________
00052 bool PedeReader::read(std::vector<Alignable*> &alignables, bool setUserVars)
00053 {
00054   alignables.clear();
00055   myPedeResult.seekg(0, std::ios::beg); // back to start
00056   bool isAllOk = true;
00057   
00058   std::set<Alignable*> uniqueList;
00059   
00060   edm::LogInfo("Alignment") << "@SUB=PedeReader::read"
00061                             << "will read parameters for run range "
00062                             << myRunRange.first << " - " << myRunRange.second;
00063   
00064   // loop on lines of text file
00065   unsigned int nParam = 0, nParamCalib = 0, nParamUnknown = 0;
00066   while (myPedeResult.good() && !myPedeResult.eof()) {
00067     // read label
00068     unsigned int paramLabel = 0;
00069     if (!this->readIfSameLine<unsigned int>(myPedeResult, paramLabel)) continue; // empty line?
00070 
00071     // read up to maximal number of pede result per parameter
00072     float buffer[myMaxNumValPerParam] = {0.};
00073     unsigned int bufferPos = 0;
00074     for ( ; bufferPos < myMaxNumValPerParam; ++bufferPos) {
00075       if (!this->readIfSameLine<float>(myPedeResult, buffer[bufferPos])) break;
00076     }
00077     
00078     // First check whether parameter is from any calibration (to be done before RunRange check:
00079     // run dependence for them is not handled here, but probably inside the calibration).
00080     // Double setting by calling read(..) twice for different RunRanges shouldn't harm.
00081     std::pair<IntegratedCalibrationBase*, unsigned int> calibParam
00082       = myLabels.calibrationParamFromLabel(paramLabel);
00083     if (calibParam.first) { // label belongs to a calibration
00084       if (this->setCalibrationParameter(calibParam.first, calibParam.second, bufferPos, buffer)) {
00085         ++nParamCalib;
00086       } else {
00087         edm::LogError("Alignment") << "@SUB=PedeReader::read" << "Problems setting results of "
00088                                    << "parameter " << calibParam.second << " to calibration '"
00089                                    << calibParam.first->name() << "' ("<< calibParam.first << ").";
00090         isAllOk = false;
00091       }
00092       continue; // does not belong to any Alignable, so go to next line of file 
00093     }
00094     // Now treat Alignables if paramLabel fits to run range, otherwise skip line:
00095     const RunRange & runRange = myLabels.runRangeFromLabel(paramLabel);
00096     if (!(runRange.first<=myRunRange.first && myRunRange.second<=runRange.second)) continue;
00097     
00098     Alignable *alignable = this->setParameter(paramLabel, bufferPos, buffer, setUserVars);
00099     if (!alignable) {
00100       // OK, e.g. for PedeReaderInputs: calibration parameters, but not yet known to labeler
00101       ++nParamUnknown;
00102       continue;
00103     }
00104     uniqueList.insert(alignable);
00105     ++nParam;
00106   }
00107 
00108   // add Alignables to output
00109   alignables.insert(alignables.end(), uniqueList.begin(), uniqueList.end());
00110 
00111   std::stringstream out; // "@SUB=PedeReader::read" cannot yet go to 'out' for proper format
00112   out << nParam << " parameters for " << alignables.size() << " alignables and " << nParamCalib
00113       << " for calibrations, " << nParamUnknown << " parameters are unknown.\n";
00114   if (nParamUnknown) {
00115     edm::LogWarning("Alignment") << "@SUB=PedeReader::read" << out.str();
00116   } else {
00117     edm::LogInfo("Alignment") << "@SUB=PedeReader::read" << out.str();
00118   }
00119 
00120   return isAllOk && (nParam + nParamCalib); // nParam+nParamCalib == 0: empty or bad file
00121 }
00122 
00123 
00124 //__________________________________________________________________________________________________
00125 template<class T> 
00126 bool PedeReader::readIfSameLine(std::ifstream &aStream, T &outValue) const
00127 {
00128 
00129   while (true) {
00130     const int aChar = aStream.get();
00131     if (!aStream.good()) return false;
00132 
00133     switch(aChar) {
00134     case ' ':
00135     case '\t':
00136       continue; // to next character
00137     case '\n':
00138       return false; // end of line
00139     default:
00140       aStream.unget();
00141       aStream >> outValue;
00142       if (aStream.fail()) {// not correct type 'T' (!aStream.good() is true also in case of EOF)
00143         aStream.clear();
00144         while (aStream.good() && aStream.get() != '\n'); // forward to end of line
00145         return false; 
00146       } else {
00147         return true;
00148       }
00149     } // switch
00150   } // while
00151 
00152   edm::LogError("Alignment") << "@SUB=PedeReader::readIfSameLine" << "Should never come here!";
00153   return false;
00154 }
00155 
00156 //__________________________________________________________________________________________________
00157 Alignable* PedeReader::setParameter(unsigned int paramLabel,
00158                                     unsigned int bufLength, const float *buf,
00159                                     bool setUserVars) const
00160 {
00161   Alignable *alignable = myLabels.alignableFromLabel(paramLabel);
00162   const unsigned int paramNum = myLabels.paramNumFromLabel(paramLabel);
00163   const double cmsToPede = mySteerer.cmsToPedeFactor(paramNum);
00164   if (alignable) {
00165     AlignmentParameters *params = this->checkAliParams(alignable, setUserVars);
00166     MillePedeVariables *userParams = // static cast ensured by previous checkAliParams
00167       (setUserVars ? static_cast<MillePedeVariables*>(params->userVariables()) : 0);
00168     // if (userParams && userParams->label() != myLabels.alignableLabelFromLabel(paramLabel)) {
00169     if (userParams && userParams->label() != myLabels.alignableLabel(alignable)) {
00170       edm::LogError("Alignment") << "@SUB=PedeReader::setParameter" 
00171                                  << "Label mismatch: paramLabel " << paramLabel 
00172                                  << " for alignableLabel " << userParams->label();
00173     }
00174 
00175     AlgebraicVector parVec(params->parameters());
00176     AlgebraicSymMatrix covMat(params->covariance());
00177 
00178     if (userParams) userParams->setAllDefault(paramNum);
00179 
00180     switch (bufLength) {
00181     case 5: // global correlation
00182       if (userParams) userParams->globalCor()[paramNum] = buf[4]; // no break
00183     case 4: // uncertainty
00184       if (userParams) userParams->sigma()[paramNum] = buf[3] / cmsToPede;
00185       covMat[paramNum][paramNum] = buf[3]*buf[3] / (cmsToPede*cmsToPede);
00186       // no break;
00187     case 3: // difference to start value
00188       if (userParams) userParams->diffBefore()[paramNum] = buf[2] / cmsToPede;
00189       // no break
00190     case 2: 
00191       params->setValid(true);
00192       parVec[paramNum] = buf[0] / cmsToPede * mySteerer.parameterSign(); // parameter
00193       if (userParams) {
00194         userParams->parameter()[paramNum] = parVec[paramNum]; // duplicate in millepede parameters
00195         userParams->preSigma()[paramNum] = buf[1];  // presigma given, probably means fixed
00196         if (!userParams->isFixed(paramNum)) {
00197           userParams->preSigma()[paramNum] /= cmsToPede;
00198           if (bufLength == 2) {
00199             edm::LogWarning("Alignment") << "@SUB=PedeReader::setParameter"
00200                                          << "Param " << paramLabel << " (from "
00201                                          << typeid(*alignable).name() << ") without result!";
00202             userParams->isValid()[paramNum] = false;
00203             params->setValid(false);
00204           }
00205         }
00206       }
00207       break;
00208     case 0:
00209     case 1:
00210     default:
00211       edm::LogError("Alignment") << "@SUB=PedeReader::setParameter"
00212                                  << "Expect 2 to 5 values, got " << bufLength 
00213                                  << " for label " << paramLabel;
00214       break;
00215     }
00216     alignable->setAlignmentParameters(params->clone(parVec, covMat));//transferred mem. responsib.
00217   } else {
00218     unsigned int lasBeamId = myLabels.lasBeamIdFromLabel(paramLabel);
00219     edm::LogError("Alignment") << "@SUB=PedeReader::setParameter"
00220                                << "No alignable for paramLabel " << paramLabel
00221                                << ", probably LasBeam with Id " << lasBeamId
00222                                << ",\nparam " << paramNum << ": " 
00223                                << buf[0] / cmsToPede * mySteerer.parameterSign()
00224                                << " += " << (bufLength >= 4 ? buf[3] / cmsToPede : -99.);
00225   }
00226 
00227   return alignable;
00228 }
00229 
00230 //__________________________________________________________________________________________________
00231 bool PedeReader::setCalibrationParameter(IntegratedCalibrationBase* calib, unsigned int paramNum,
00232                                          unsigned int bufLength, const float *buf) const
00233 {
00234   if (!calib || !buf) return false;
00235 
00236   // FIXME: Should we attach MillePedeVariables to IntegratedCalibrationBase to store
00237   //        'other' results beyond value and error?
00238   switch (bufLength) {
00239   case 5: // buf[4]: global correlation - not treated yet FIXME // no break;
00240   case 4: // uncertainty
00241     calib->setParameterError(paramNum, buf[3]); // no break;
00242   case 3: // buf[2]: difference to start value - not treated yet // no break;
00243   case 2:
00244     if (bufLength == 2 && buf[1] >= 0.) { // buf[1]: pre-sigma, < 0 means fixed
00245       edm::LogWarning("Alignment") << "@SUB=PedeReader::setCalibrationParameter"
00246                                    << "Param " << paramNum << " of calibration '"
00247                                    << calib->name() << "' without result!";
00248     }
00249     return calib->setParameter(paramNum, buf[0] * mySteerer.parameterSign());
00250   case 0:
00251   case 1:
00252   default:
00253     edm::LogError("Alignment") << "@SUB=PedeReader::setCalibrationParameter"
00254                                << "Expect 2 to 5 values, got " << bufLength << "."; 
00255     return false;
00256   }
00257 
00258 }
00259 
00260 //__________________________________________________________________________________________________
00261 AlignmentParameters* PedeReader::checkAliParams(Alignable *alignable, bool createUserVars) const
00262 {
00263   // first check that we have parameters
00264   AlignmentParameters *params = alignable->alignmentParameters();
00265   if (!params) {
00266     throw cms::Exception("BadConfig") << "PedeReader::checkAliParams: "
00267                                       << "Alignable without parameters.";
00268 
00269   }
00270   
00271   // now check that we have user parameters of correct type if requested:
00272   if (createUserVars && !dynamic_cast<MillePedeVariables*>(params->userVariables())) {
00273     edm::LogInfo("Alignment") << "@SUB=PedeReader::checkAliParams"
00274                               << "Add user variables for alignable with label " 
00275                               << myLabels.alignableLabel(alignable);
00276     params->setUserVariables(new MillePedeVariables(params->size(), myLabels.alignableLabel(alignable)));
00277   }
00278   
00279   return params;
00280 }