CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/Alignment/CommonAlignmentAlgorithm/plugins/SiStripLorentzAngleCalibration.cc

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 #include "Alignment/CommonAlignmentAlgorithm/interface/IntegratedCalibrationBase.h"
00015 #include "Alignment/CommonAlignmentAlgorithm/interface/TkModuleGroupSelector.h"
00016 // include 'locally':
00017 #include "SiStripReadoutModeEnums.h"
00018 #include "TreeStruct.h"
00019 
00020 #include "CondCore/DBOutputService/interface/PoolDBOutputService.h"
00021 #include "CondFormats/DataRecord/interface/SiStripCondDataRecords.h"
00022 #include "CondFormats/SiStripObjects/interface/SiStripLatency.h"
00023 #include "CondFormats/SiStripObjects/interface/SiStripLorentzAngle.h"
00024 //#include "CalibTracker/Records/interface/SiStripDependentRecords.h"
00025 #include "CondFormats/SiStripObjects/interface/SiStripBackPlaneCorrection.h"
00026 
00027 #include "DataFormats/DetId/interface/DetId.h"
00028 #include "DataFormats/SiStripDetId/interface/SiStripDetId.h"
00029 
00030 #include "FWCore/Framework/interface/ESHandle.h"
00031 #include "FWCore/Framework/interface/ESWatcher.h"
00032 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00033 #include "FWCore/ServiceRegistry/interface/Service.h"
00034 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00035 
00036 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
00037 #include "MagneticField/Engine/interface/MagneticField.h"
00038 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00039 #include "TrackingTools/TransientTrackingRecHit/interface/TransientTrackingRecHit.h"
00040 
00041 #include "TTree.h"
00042 #include "TFile.h"
00043 #include "TString.h"
00044 
00045 // #include <iostream>
00046 #include <boost/assign/list_of.hpp>
00047 #include <vector>
00048 #include <map>
00049 #include <sstream>
00050 #include <cstdio>
00051 #include <functional>
00052 
00053 class SiStripLorentzAngleCalibration : public IntegratedCalibrationBase
00054 {
00055 public:
00057   explicit SiStripLorentzAngleCalibration(const edm::ParameterSet &cfg);
00058   
00060   virtual ~SiStripLorentzAngleCalibration();
00061 
00063   virtual unsigned int numParameters() const;
00064 
00065   // /// Return all derivatives,
00066   // /// default implementation uses other derivatives(..) method,
00067   // /// but can be overwritten in derived class for efficiency.
00068   // virtual std::vector<double> derivatives(const TransientTrackingRecHit &hit,
00069   //                                      const TrajectoryStateOnSurface &tsos,
00070   //                                      const edm::EventSetup &setup,
00071   //                                      const EventInfo &eventInfo) const;
00072 
00075   virtual unsigned int derivatives(std::vector<ValuesIndexPair> &outDerivInds,
00076                                    const TransientTrackingRecHit &hit,
00077                                    const TrajectoryStateOnSurface &tsos,
00078                                    const edm::EventSetup &setup,
00079                                    const EventInfo &eventInfo) const;
00080 
00083   virtual bool setParameter(unsigned int index, double value);
00084 
00087   virtual bool setParameterError(unsigned int index, double error);
00088 
00091   virtual double getParameter(unsigned int index) const;
00092 
00095   virtual double getParameterError(unsigned int index) const;
00096 
00097   // /// Call at beginning of job:
00098   virtual void beginOfJob(AlignableTracker *tracker,
00099                           AlignableMuon *muon,
00100                           AlignableExtras *extras);
00101   
00102 
00105   virtual void endOfJob();
00106 
00107 private:
00110   bool checkLorentzAngleInput(const edm::EventSetup &setup, const EventInfo &eventInfo);
00114   const SiStripLorentzAngle* getLorentzAnglesInput();
00116   double effectiveThickness(const GeomDet *det, int16_t mode, const edm::EventSetup &setup) const;
00117 
00120   double getParameterForDetId(unsigned int detId, edm::RunNumber_t run) const;
00121 
00122   void writeTree(const SiStripLorentzAngle *lorentzAngle,
00123                  const std::map<unsigned int,TreeStruct> &treeInfo, const char *treeName) const;
00124   SiStripLorentzAngle* createFromTree(const char *fileName, const char *treeName) const;
00125   
00126   const std::string readoutModeName_;
00127   int16_t readoutMode_;
00128   const bool saveToDB_;
00129   const std::string recordNameDBwrite_;
00130   const std::string outFileName_;
00131   const std::vector<std::string> mergeFileNames_;
00132 
00133   edm::ESWatcher<SiStripLorentzAngleRcd> watchLorentzAngleRcd_;
00134 
00135   SiStripLorentzAngle *siStripLorentzAngleInput_;
00136 
00137   std::vector<double> parameters_;
00138   std::vector<double> paramUncertainties_;
00139 
00140   TkModuleGroupSelector *moduleGroupSelector_;
00141   const edm::ParameterSet moduleGroupSelCfg_;
00142 };
00143 
00144 //======================================================================
00145 //======================================================================
00146 //======================================================================
00147 
00148 SiStripLorentzAngleCalibration::SiStripLorentzAngleCalibration(const edm::ParameterSet &cfg)
00149   : IntegratedCalibrationBase(cfg),
00150     readoutModeName_(cfg.getParameter<std::string>("readoutMode")),
00151     saveToDB_(cfg.getParameter<bool>("saveToDB")),
00152     recordNameDBwrite_(cfg.getParameter<std::string>("recordNameDBwrite")),
00153     outFileName_(cfg.getParameter<std::string>("treeFile")),
00154     mergeFileNames_(cfg.getParameter<std::vector<std::string> >("mergeTreeFiles")),
00155     siStripLorentzAngleInput_(0),
00156     moduleGroupSelector_(0),
00157     moduleGroupSelCfg_(cfg.getParameter<edm::ParameterSet>("LorentzAngleModuleGroups"))
00158 {
00159 
00160   // SiStripLatency::singleReadOutMode() returns
00161   // 1: all in peak, 0: all in deco, -1: mixed state
00162   // (in principle one could treat even mixed state APV by APV...)
00163   if (readoutModeName_ == "peak") {
00164     readoutMode_ = kPeakMode;
00165   } else if (readoutModeName_ == "deconvolution") {
00166     readoutMode_ = kDeconvolutionMode;
00167   } else {
00168     throw cms::Exception("BadConfig")
00169           << "SiStripLorentzAngleCalibration:\n" << "Unknown mode '" 
00170           << readoutModeName_ << "', should be 'peak' or 'deconvolution' .\n";
00171   }
00172 
00173 }
00174   
00175 //======================================================================
00176 SiStripLorentzAngleCalibration::~SiStripLorentzAngleCalibration()
00177 {
00178   delete moduleGroupSelector_;
00179   //  std::cout << "Destroy SiStripLorentzAngleCalibration named " << this->name() << std::endl;
00180   delete siStripLorentzAngleInput_;
00181 }
00182 
00183 //======================================================================
00184 unsigned int SiStripLorentzAngleCalibration::numParameters() const
00185 {
00186   return parameters_.size();
00187 }
00188 
00189 //======================================================================
00190 unsigned int
00191 SiStripLorentzAngleCalibration::derivatives(std::vector<ValuesIndexPair> &outDerivInds,
00192                                             const TransientTrackingRecHit &hit,
00193                                             const TrajectoryStateOnSurface &tsos,
00194                                             const edm::EventSetup &setup,
00195                                             const EventInfo &eventInfo) const
00196 {
00197   // ugly const-cast:
00198   // But it is either only first initialisation or throwing an exception...
00199   const_cast<SiStripLorentzAngleCalibration*>(this)->checkLorentzAngleInput(setup, eventInfo);
00200 
00201   outDerivInds.clear();
00202 
00203   edm::ESHandle<SiStripLatency> latency;  
00204   setup.get<SiStripLatencyRcd>().get(latency);
00205   const int16_t mode = latency->singleReadOutMode();
00206   if (mode == readoutMode_) {
00207     if (hit.det()) { // otherwise 'constraint hit' or whatever
00208       
00209       const int index = moduleGroupSelector_->getParameterIndexFromDetId(hit.det()->geographicalId(),
00210                                                                     eventInfo.eventId_.run());
00211       if (index >= 0) { // otherwise not treated
00212         edm::ESHandle<MagneticField> magneticField;
00213         setup.get<IdealMagneticFieldRecord>().get(magneticField);
00214         const GlobalVector bField(magneticField->inTesla(hit.det()->surface().position()));
00215         const LocalVector bFieldLocal(hit.det()->surface().toLocal(bField));
00216         //std::cout << "SiStripLorentzAngleCalibration derivatives " << readoutModeName_ << std::endl;
00217         const double dZ = this->effectiveThickness(hit.det(), mode, setup);
00218         // shift due to LA: dx = tan(LA) * dz/2 = mobility * B_y * dz/2,
00219         // '-' since we have derivative of the residual r = hit - trk and mu is part of trk model
00220         //   (see GF's presentation in alignment meeting 25.10.2012,
00221         //    https://indico.cern.ch/conferenceDisplay.py?confId=174266#2012-10-25)
00222         // Hmm! StripCPE::fillParams() defines, together with 
00223         //      StripCPE::driftDirection(...):
00224         //      drift.x = -mobility * by * thickness (full drift from backside)
00225         //      So '-' already comes from that, not from mobility being part of
00226         //      track model...
00227         const double xDerivative = bFieldLocal.y() * dZ * -0.5; // parameter is mobility!
00228         if (xDerivative) { // If field is zero, this is zero: do not return it
00229           const Values derivs(xDerivative, 0.); // yDerivative = 0.
00230           outDerivInds.push_back(ValuesIndexPair(derivs, index));
00231         }
00232       }
00233     } else {
00234       edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::derivatives1"
00235                                    << "Hit without GeomDet, skip!";
00236     }
00237   } else if (mode != kDeconvolutionMode && mode != kPeakMode) {
00238     // warn only if unknown/mixed mode  
00239     edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::derivatives2"
00240                                  << "Readout mode is " << mode << ", but looking for "
00241                                  << readoutMode_ << " (" << readoutModeName_ << ").";
00242   }
00243   
00244   return outDerivInds.size();
00245 }
00246 
00247 //======================================================================
00248 bool SiStripLorentzAngleCalibration::setParameter(unsigned int index, double value)
00249 {
00250   if (index >= parameters_.size()) {
00251     return false;
00252   } else {
00253     parameters_[index] = value;
00254     return true;
00255   }
00256 }
00257 
00258 //======================================================================
00259 bool SiStripLorentzAngleCalibration::setParameterError(unsigned int index, double error)
00260 {
00261   if (index >= paramUncertainties_.size()) {
00262     return false;
00263   } else {
00264     paramUncertainties_[index] = error;
00265     return true;
00266   }
00267 }
00268 
00269 //======================================================================
00270 double SiStripLorentzAngleCalibration::getParameter(unsigned int index) const
00271 {
00272   return (index >= parameters_.size() ? 0. : parameters_[index]);
00273 }
00274 
00275 //======================================================================
00276 double SiStripLorentzAngleCalibration::getParameterError(unsigned int index) const
00277 {
00278   return (index >= paramUncertainties_.size() ? 0. : paramUncertainties_[index]);
00279 }
00280 
00281 //======================================================================
00282 void SiStripLorentzAngleCalibration::beginOfJob(AlignableTracker *aliTracker,
00283                                                 AlignableMuon * /*aliMuon*/,
00284                                                 AlignableExtras * /*aliExtras*/)
00285 {
00286   //specify the sub-detectors for which the LA is determined
00287   const std::vector<int> sdets = boost::assign::list_of(SiStripDetId::TIB)(SiStripDetId::TOB); //no TEC,TID
00288   moduleGroupSelector_ = new TkModuleGroupSelector(aliTracker, moduleGroupSelCfg_, sdets);
00289  
00290   parameters_.resize(moduleGroupSelector_->getNumberOfParameters(), 0.);
00291   paramUncertainties_.resize(moduleGroupSelector_->getNumberOfParameters(), 0.);
00292 
00293   edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration" << "Created with name "
00294                             << this->name() << " for readout mode '" << readoutModeName_
00295                             << "',\n" << this->numParameters() << " parameters to be determined."
00296                             << "\nsaveToDB = " << saveToDB_
00297                             << "\n outFileName = " << outFileName_
00298                             << "\n N(merge files) = " << mergeFileNames_.size()
00299                             << "\n number of IOVs = " << moduleGroupSelector_->numIovs();
00300 
00301   if (mergeFileNames_.size()) {
00302     edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration"
00303                               << "First file to merge: " << mergeFileNames_[0];
00304   }
00305 }
00306 
00307 
00308 //======================================================================
00309 void SiStripLorentzAngleCalibration::endOfJob()
00310 {
00311   // loginfo output
00312   std::ostringstream out;
00313   out << "Parameter results for readout mode '" << readoutModeName_ << "'\n";
00314   for (unsigned int iPar = 0; iPar < parameters_.size(); ++iPar) {
00315     out << iPar << ": " << parameters_[iPar] << " +- " << paramUncertainties_[iPar] << "\n";
00316   }
00317   edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration::endOfJob" << out.str();
00318 
00319   std::map<unsigned int, TreeStruct> treeInfo; // map of TreeStruct for each detId
00320 
00321   // now write 'input' tree
00322   const SiStripLorentzAngle *input = this->getLorentzAnglesInput(); // never NULL
00323   const std::string treeName(this->name() + '_' + readoutModeName_ + '_');
00324   this->writeTree(input, treeInfo, (treeName + "input").c_str()); // empty treeInfo for input...
00325 
00326   if (input->getLorentzAngles().empty()) {
00327     edm::LogError("Alignment") << "@SUB=SiStripLorentzAngleCalibration::endOfJob"
00328                                << "Input Lorentz angle map is empty ('"
00329                                << readoutModeName_ << "' mode), skip writing output!";
00330     return;
00331   }
00332 
00333   const unsigned int nonZeroParamsOrErrors =   // Any determined value?
00334     count_if (parameters_.begin(), parameters_.end(), std::bind2nd(std::not_equal_to<double>(),0.))
00335     + count_if(paramUncertainties_.begin(), paramUncertainties_.end(),
00336                std::bind2nd(std::not_equal_to<double>(), 0.));
00337 
00338   for (unsigned int iIOV = 0; iIOV < moduleGroupSelector_->numIovs(); ++iIOV) {
00339     cond::Time_t firstRunOfIOV = moduleGroupSelector_->firstRunOfIOV(iIOV);
00340     SiStripLorentzAngle *output = new SiStripLorentzAngle;
00341     // Loop on map of values from input and add (possible) parameter results
00342     for (auto iterIdValue = input->getLorentzAngles().begin();
00343          iterIdValue != input->getLorentzAngles().end(); ++iterIdValue) {
00344       // type of (*iterIdValue) is pair<unsigned int, float>
00345       const unsigned int detId = iterIdValue->first; // key of map is DetId
00346       // Some code one could use to miscalibrate wrt input:
00347       // double param = 0.;
00348       // const DetId id(detId);
00349       // if (id.subdetId() == 3) { // TIB
00350       //   param = (readoutMode_ == kPeakMode ? -0.003 : -0.002);
00351       // } else if (id.subdetId() == 5) { // TOB
00352       //   param = (readoutMode_ == kPeakMode ? 0.005 : 0.004);
00353       // }
00354       const double param = this->getParameterForDetId(detId, firstRunOfIOV);
00355       // put result in output, i.e. sum of input and determined parameter:
00356       output->putLorentzAngle(detId, iterIdValue->second + param);
00357       const int paramIndex = moduleGroupSelector_->getParameterIndexFromDetId(detId,firstRunOfIOV);
00358       treeInfo[detId] = TreeStruct(param, this->getParameterError(paramIndex), paramIndex);
00359     }
00360 
00361     if (saveToDB_ || nonZeroParamsOrErrors != 0) { // Skip writing mille jobs...
00362       this->writeTree(output, treeInfo, (treeName + Form("result_%lld", firstRunOfIOV)).c_str());
00363     }
00364 
00365     if (saveToDB_) { // If requested, write out to DB 
00366       edm::Service<cond::service::PoolDBOutputService> dbService;
00367       if (dbService.isAvailable()) {
00368         dbService->writeOne(output, firstRunOfIOV, recordNameDBwrite_.c_str());
00369         // no 'delete output;': writeOne(..) took over ownership
00370       } else {
00371         delete output;
00372         edm::LogError("BadConfig") << "@SUB=SiStripLorentzAngleCalibration::endOfJob"
00373                                    << "No PoolDBOutputService available, but saveToDB true!";
00374       }
00375     } else {
00376       delete output;
00377     }
00378   } // end loop on IOVs
00379 }
00380 
00381 //======================================================================
00382 bool SiStripLorentzAngleCalibration::checkLorentzAngleInput(const edm::EventSetup &setup,
00383                                                             const EventInfo &eventInfo)
00384 {
00385   edm::ESHandle<SiStripLorentzAngle> lorentzAngleHandle;
00386   if (!siStripLorentzAngleInput_) {
00387     setup.get<SiStripLorentzAngleRcd>().get(readoutModeName_, lorentzAngleHandle);
00388     siStripLorentzAngleInput_ = new SiStripLorentzAngle(*lorentzAngleHandle);
00389     // FIXME: Should we call 'watchLorentzAngleRcd_.check(setup)' as well?
00390     //        Otherwise could be that next check has to check via following 'else', though
00391     //        no new IOV has started... (to be checked)
00392   } else {
00393     if (watchLorentzAngleRcd_.check(setup)) { // new IOV of input - but how to check peak vs deco?
00394       setup.get<SiStripLorentzAngleRcd>().get(readoutModeName_, lorentzAngleHandle);
00395       if (lorentzAngleHandle->getLorentzAngles() // but only bad if non-identical values
00396           != siStripLorentzAngleInput_->getLorentzAngles()) { // (comparing maps)
00397         // Maps are containers sorted by key, but comparison problems may arise from
00398         // 'floating point comparison' problems (FIXME?)
00399         throw cms::Exception("BadInput")
00400           << "SiStripLorentzAngleCalibration::checkLorentzAngleInput:\n"
00401           << "Content of SiStripLorentzAngle changed at run " << eventInfo.eventId_.run()
00402           << ", but algorithm expects constant input!\n";
00403         return false; // not reached...
00404       }
00405     }
00406   }
00407   
00408   return true;
00409 }
00410 
00411 //======================================================================
00412 double SiStripLorentzAngleCalibration::effectiveThickness(const GeomDet *det,
00413                                                           int16_t mode,
00414                                                           const edm::EventSetup &setup) const
00415 {
00416   if (!det) return 0.;
00417   double dZ = det->surface().bounds().thickness(); // it is a float only...
00418   const SiStripDetId id(det->geographicalId());
00419   edm::ESHandle<SiStripBackPlaneCorrection> backPlaneHandle;
00420   // FIXME: which one? DepRcd->get(handle) or Rcd->get(readoutModeName_, handle)??
00421   // setup.get<SiStripBackPlaneCorrectionDepRcd>().get(backPlaneHandle); // get correct mode
00422   setup.get<SiStripBackPlaneCorrectionRcd>().get(readoutModeName_, backPlaneHandle);
00423   const double bpCor = backPlaneHandle->getBackPlaneCorrection(id); // it's a float...
00424   //  std::cout << "bpCor " << bpCor << " in subdet " << id.subdetId() << std::endl;
00425   dZ *= (1. - bpCor);
00426  
00427   return dZ;
00428 } 
00429 
00430 //======================================================================
00431 const SiStripLorentzAngle* SiStripLorentzAngleCalibration::getLorentzAnglesInput()
00432 {
00433   // For parallel processing in Millepede II, create SiStripLorentzAngle
00434   // from info stored in files of parallel jobs and check that they are identical.
00435   // If this job has run on events, still check that LA is identical to the ones
00436   // from mergeFileNames_.
00437   const std::string treeName(((this->name() + '_') += readoutModeName_) += "_input");
00438   for (auto iFile = mergeFileNames_.begin(); iFile != mergeFileNames_.end(); ++iFile) {
00439     SiStripLorentzAngle* la = this->createFromTree(iFile->c_str(), treeName.c_str());
00440     // siStripLorentzAngleInput_ could be non-null from previous file of this loop
00441     // or from checkLorentzAngleInput(..) when running on data in this job as well
00442     if (!siStripLorentzAngleInput_ || siStripLorentzAngleInput_->getLorentzAngles().empty()) {
00443       delete siStripLorentzAngleInput_; // NULL or empty
00444       siStripLorentzAngleInput_ = la;
00445     } else {
00446       // FIXME: about comparison of maps see comments in checkLorentzAngleInput
00447       if (la && !la->getLorentzAngles().empty() && // single job might not have got events
00448           la->getLorentzAngles() != siStripLorentzAngleInput_->getLorentzAngles()) {
00449         // Throw exception instead of error?
00450         edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
00451                                  << "Different input values from tree " << treeName
00452                                  << " in file " << *iFile << ".";
00453         
00454       }
00455       delete la;
00456     }
00457   }
00458 
00459   if (!siStripLorentzAngleInput_) { // no files nor ran on events
00460     siStripLorentzAngleInput_ = new SiStripLorentzAngle;
00461     edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
00462                              << "No input, create an empty one ('" << readoutModeName_ << "' mode)!";
00463   } else if (siStripLorentzAngleInput_->getLorentzAngles().empty()) {
00464     edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
00465                              << "Empty result ('" << readoutModeName_ << "' mode)!";
00466   }
00467 
00468   return siStripLorentzAngleInput_;
00469 }
00470 
00471 //======================================================================
00472 double SiStripLorentzAngleCalibration::getParameterForDetId(unsigned int detId,
00473                                                             edm::RunNumber_t run) const
00474 {
00475   const int index = moduleGroupSelector_->getParameterIndexFromDetId(detId, run);
00476 
00477   return (index < 0 ? 0. : parameters_[index]);
00478 }
00479 
00480 //======================================================================
00481 void SiStripLorentzAngleCalibration::writeTree(const SiStripLorentzAngle *lorentzAngle,
00482                                                const std::map<unsigned int, TreeStruct> &treeInfo,
00483                                                const char *treeName) const
00484 {
00485   if (!lorentzAngle) return;
00486 
00487   TFile* file = TFile::Open(outFileName_.c_str(), "UPDATE");
00488   if (!file) {
00489     edm::LogError("BadConfig") << "@SUB=SiStripLorentzAngleCalibration::writeTree"
00490                                << "Could not open file '" << outFileName_ << "'.";
00491     return;
00492   }
00493 
00494   TTree *tree = new TTree(treeName, treeName);
00495   unsigned int id = 0;
00496   float value = 0.;
00497   TreeStruct treeStruct;
00498   tree->Branch("detId", &id, "detId/i");
00499   tree->Branch("value", &value, "value/F");
00500   tree->Branch("treeStruct", &treeStruct, TreeStruct::LeafList());
00501 
00502   for (auto iterIdValue = lorentzAngle->getLorentzAngles().begin();
00503        iterIdValue != lorentzAngle->getLorentzAngles().end(); ++iterIdValue) {
00504     // type of (*iterIdValue) is pair<unsigned int, float>
00505     id = iterIdValue->first; // key of map is DetId
00506     value = iterIdValue->second;
00507     // type of (*treeStructIter) is pair<unsigned int, TreeStruct>
00508     auto treeStructIter = treeInfo.find(id); // find info for this id
00509     if (treeStructIter != treeInfo.end()) {
00510       treeStruct = treeStructIter->second; // info from input map
00511     } else { // if none found, fill at least parameter index (using 1st IOV...)
00512       const cond::Time_t run1of1stIov = moduleGroupSelector_->firstRunOfIOV(0);
00513       const int ind = moduleGroupSelector_->getParameterIndexFromDetId(id, run1of1stIov);
00514       treeStruct = TreeStruct(ind);
00515     }
00516     tree->Fill();
00517   }
00518   tree->Write();
00519   delete file; // tree vanishes with the file...
00520 }
00521 
00522 //======================================================================
00523 SiStripLorentzAngle* 
00524 SiStripLorentzAngleCalibration::createFromTree(const char *fileName, const char *treeName) const
00525 {
00526   // Check for file existence on your own to work around
00527   // https://hypernews.cern.ch/HyperNews/CMS/get/swDevelopment/2715.html:
00528   TFile* file = 0;
00529   FILE* testFile = fopen(fileName,"r");
00530   if (testFile) {
00531     fclose(testFile);
00532     file = TFile::Open(fileName, "READ");
00533   } // else not existing, see error below
00534 
00535   TTree *tree = 0;
00536   if (file) file->GetObject(treeName, tree);
00537 
00538   SiStripLorentzAngle *result = 0;
00539   if (tree) {
00540     unsigned int id = 0;
00541     float value = 0.;
00542     tree->SetBranchAddress("detId", &id);
00543     tree->SetBranchAddress("value", &value);
00544 
00545     result = new SiStripLorentzAngle;
00546     const Long64_t nEntries = tree->GetEntries();
00547     for (Long64_t iEntry = 0; iEntry < nEntries; ++iEntry) {
00548       tree->GetEntry(iEntry);
00549       result->putLorentzAngle(id, value);
00550     }
00551   } else { // Warning only since could be parallel job on no events.
00552     edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::createFromTree"
00553                                  << "Could not get TTree '" << treeName << "' from file '"
00554                                  << fileName << (file ? "'." : "' (file does not exist).");
00555   }
00556 
00557   delete file; // tree will vanish with file
00558   return result;
00559 }
00560 
00561 
00562 //======================================================================
00563 //======================================================================
00564 // Plugin definition
00565 
00566 #include "Alignment/CommonAlignmentAlgorithm/interface/IntegratedCalibrationPluginFactory.h"
00567 
00568 DEFINE_EDM_PLUGIN(IntegratedCalibrationPluginFactory,
00569                    SiStripLorentzAngleCalibration, "SiStripLorentzAngleCalibration");