CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC2_patch1/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 <map>
00027 #include <string>
00028 
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::map<Alignable*,Alignable*> uniqueList; // Probably should use a std::set here...
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;
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       isAllOk = false;  // or error?
00101       continue;
00102     }
00103     uniqueList[alignable] = alignable;
00104     ++nParam;
00105   }
00106 
00107   // add Alignables to output
00108   for ( std::map<Alignable*,Alignable*>::const_iterator iAli = uniqueList.begin();
00109         iAli != uniqueList.end(); ++iAli) {
00110     alignables.push_back((*iAli).first);
00111   }
00112 
00113   edm::LogInfo("Alignment") << "@SUB=PedeReader::read" << nParam << " parameters for "
00114                             << alignables.size() << " alignables and " << nParamCalib
00115                             << " for calibrations.";
00116 
00117   return isAllOk && (nParam + nParamCalib); // nParam+nParamCalib == 0: empty or bad file
00118 }
00119 
00120 
00121 //__________________________________________________________________________________________________
00122 template<class T> 
00123 bool PedeReader::readIfSameLine(std::ifstream &aStream, T &outValue) const
00124 {
00125 
00126   while (true) {
00127     const int aChar = aStream.get();
00128     if (!aStream.good()) return false;
00129 
00130     switch(aChar) {
00131     case ' ':
00132     case '\t':
00133       continue; // to next character
00134     case '\n':
00135       return false; // end of line
00136     default:
00137       aStream.unget();
00138       aStream >> outValue;
00139       if (aStream.fail()) {// not correct type 'T' (!aStream.good() is true also in case of EOF)
00140         aStream.clear();
00141         while (aStream.good() && aStream.get() != '\n'); // forward to end of line
00142         return false; 
00143       } else {
00144         return true;
00145       }
00146     } // switch
00147   } // while
00148 
00149   edm::LogError("Alignment") << "@SUB=PedeReader::readIfSameLine" << "Should never come here!";
00150   return false;
00151 }
00152 
00153 //__________________________________________________________________________________________________
00154 Alignable* PedeReader::setParameter(unsigned int paramLabel,
00155                                     unsigned int bufLength, const float *buf,
00156                                     bool setUserVars) const
00157 {
00158   Alignable *alignable = myLabels.alignableFromLabel(paramLabel);
00159   const unsigned int paramNum = myLabels.paramNumFromLabel(paramLabel);
00160   const double cmsToPede = mySteerer.cmsToPedeFactor(paramNum);
00161   if (alignable) {
00162     AlignmentParameters *params = this->checkAliParams(alignable, setUserVars);
00163     MillePedeVariables *userParams = // static cast ensured by previous checkAliParams
00164       (setUserVars ? static_cast<MillePedeVariables*>(params->userVariables()) : 0);
00165     // if (userParams && userParams->label() != myLabels.alignableLabelFromLabel(paramLabel)) {
00166     if (userParams && userParams->label() != myLabels.alignableLabel(alignable)) {
00167       edm::LogError("Alignment") << "@SUB=PedeReader::setParameter" 
00168                                  << "Label mismatch: paramLabel " << paramLabel 
00169                                  << " for alignableLabel " << userParams->label();
00170     }
00171 
00172     AlgebraicVector parVec(params->parameters());
00173     AlgebraicSymMatrix covMat(params->covariance());
00174 
00175     if (userParams) userParams->setAllDefault(paramNum);
00176 
00177     switch (bufLength) {
00178     case 5: // global correlation
00179       if (userParams) userParams->globalCor()[paramNum] = buf[4]; // no break
00180     case 4: // uncertainty
00181       if (userParams) userParams->sigma()[paramNum] = buf[3] / cmsToPede;
00182       covMat[paramNum][paramNum] = buf[3]*buf[3] / (cmsToPede*cmsToPede);
00183       // no break;
00184     case 3: // difference to start value
00185       if (userParams) userParams->diffBefore()[paramNum] = buf[2] / cmsToPede;
00186       // no break
00187     case 2: 
00188       params->setValid(true);
00189       parVec[paramNum] = buf[0] / cmsToPede * mySteerer.parameterSign(); // parameter
00190       if (userParams) {
00191         userParams->parameter()[paramNum] = parVec[paramNum]; // duplicate in millepede parameters
00192         userParams->preSigma()[paramNum] = buf[1];  // presigma given, probably means fixed
00193         if (!userParams->isFixed(paramNum)) {
00194           userParams->preSigma()[paramNum] /= cmsToPede;
00195           if (bufLength == 2) {
00196             edm::LogWarning("Alignment") << "@SUB=PedeReader::setParameter"
00197                                          << "Param " << paramLabel << " (from "
00198                                          << typeid(*alignable).name() << ") without result!";
00199             userParams->isValid()[paramNum] = false;
00200             params->setValid(false);
00201           }
00202         }
00203       }
00204       break;
00205     case 0:
00206     case 1:
00207     default:
00208       edm::LogError("Alignment") << "@SUB=PedeReader::setParameter"
00209                                  << "Expect 2 to 5 values, got " << bufLength 
00210                                  << " for label " << paramLabel;
00211       break;
00212     }
00213     alignable->setAlignmentParameters(params->clone(parVec, covMat));//transferred mem. responsib.
00214   } else {
00215     unsigned int lasBeamId = myLabels.lasBeamIdFromLabel(paramLabel);
00216     edm::LogError("Alignment") << "@SUB=PedeReader::setParameter"
00217                                << "No alignable for paramLabel " << paramLabel
00218                                << ", probably LasBeam with Id " << lasBeamId
00219                                << ",\nparam " << paramNum << ": " 
00220                                << buf[0] / cmsToPede * mySteerer.parameterSign()
00221                                << " += " << (bufLength >= 4 ? buf[3] / cmsToPede : -99.);
00222   }
00223 
00224   return alignable;
00225 }
00226 
00227 //__________________________________________________________________________________________________
00228 bool PedeReader::setCalibrationParameter(IntegratedCalibrationBase* calib, unsigned int paramNum,
00229                                          unsigned int bufLength, const float *buf) const
00230 {
00231   if (!calib || !buf) return false;
00232 
00233   // FIXME: Should we attach MillePedeVariables to IntegratedCalibrationBase to store
00234   //        'other' results beyond value and error?
00235   switch (bufLength) {
00236   case 5: // buf[4]: global correlation - not treated yet FIXME // no break;
00237   case 4: // uncertainty
00238     calib->setParameterError(paramNum, buf[3]); // no break;
00239   case 3: // buf[2]: difference to start value - not treated yet // no break;
00240   case 2:
00241     if (bufLength == 2 && buf[1] >= 0.) { // buf[1]: pre-sigma, < 0 means fixed
00242       edm::LogWarning("Alignment") << "@SUB=PedeReader::setCalibrationParameter"
00243                                    << "Param " << paramNum << " of calibration '"
00244                                    << calib->name() << "' without result!";
00245     }
00246     return calib->setParameter(paramNum, buf[0] * mySteerer.parameterSign());
00247   case 0:
00248   case 1:
00249   default:
00250     edm::LogError("Alignment") << "@SUB=PedeReader::setCalibrationParameter"
00251                                << "Expect 2 to 5 values, got " << bufLength << "."; 
00252     return false;
00253   }
00254 
00255 }
00256 
00257 //__________________________________________________________________________________________________
00258 AlignmentParameters* PedeReader::checkAliParams(Alignable *alignable, bool createUserVars) const
00259 {
00260   // first check that we have parameters
00261   AlignmentParameters *params = alignable->alignmentParameters();
00262   if (!params) {
00263     throw cms::Exception("BadConfig") << "PedeReader::checkAliParams: "
00264                                       << "Alignable without parameters.";
00265 
00266   }
00267   
00268   // now check that we have user parameters of correct type if requested:
00269   if (createUserVars && !dynamic_cast<MillePedeVariables*>(params->userVariables())) {
00270     edm::LogInfo("Alignment") << "@SUB=PedeReader::checkAliParams"
00271                               << "Add user variables for alignable with label " 
00272                               << myLabels.alignableLabel(alignable);
00273     params->setUserVariables(new MillePedeVariables(params->size(), myLabels.alignableLabel(alignable)));
00274   }
00275   
00276   return params;
00277 }