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
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
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
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
00066
00067
00068
00069
00070
00071
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
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
00161
00162
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
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
00198
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()) {
00208
00209 const int index = moduleGroupSelector_->getParameterIndexFromDetId(hit.det()->geographicalId(),
00210 eventInfo.eventId_.run());
00211 if (index >= 0) {
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
00217 const double dZ = this->effectiveThickness(hit.det(), mode, setup);
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 const double xDerivative = bFieldLocal.y() * dZ * -0.5;
00228 if (xDerivative) {
00229 const Values derivs(xDerivative, 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
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 * ,
00284 AlignableExtras * )
00285 {
00286
00287 const std::vector<int> sdets = boost::assign::list_of(SiStripDetId::TIB)(SiStripDetId::TOB);
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
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;
00320
00321
00322 const SiStripLorentzAngle *input = this->getLorentzAnglesInput();
00323 const std::string treeName(this->name() + '_' + readoutModeName_ + '_');
00324 this->writeTree(input, treeInfo, (treeName + "input").c_str());
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 =
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
00342 for (auto iterIdValue = input->getLorentzAngles().begin();
00343 iterIdValue != input->getLorentzAngles().end(); ++iterIdValue) {
00344
00345 const unsigned int detId = iterIdValue->first;
00346
00347
00348
00349
00350
00351
00352
00353
00354 const double param = this->getParameterForDetId(detId, firstRunOfIOV);
00355
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) {
00362 this->writeTree(output, treeInfo, (treeName + Form("result_%lld", firstRunOfIOV)).c_str());
00363 }
00364
00365 if (saveToDB_) {
00366 edm::Service<cond::service::PoolDBOutputService> dbService;
00367 if (dbService.isAvailable()) {
00368 dbService->writeOne(output, firstRunOfIOV, recordNameDBwrite_.c_str());
00369
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 }
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
00390
00391
00392 } else {
00393 if (watchLorentzAngleRcd_.check(setup)) {
00394 setup.get<SiStripLorentzAngleRcd>().get(readoutModeName_, lorentzAngleHandle);
00395 if (lorentzAngleHandle->getLorentzAngles()
00396 != siStripLorentzAngleInput_->getLorentzAngles()) {
00397
00398
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;
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();
00418 const SiStripDetId id(det->geographicalId());
00419 edm::ESHandle<SiStripBackPlaneCorrection> backPlaneHandle;
00420
00421
00422 setup.get<SiStripBackPlaneCorrectionRcd>().get(readoutModeName_, backPlaneHandle);
00423 const double bpCor = backPlaneHandle->getBackPlaneCorrection(id);
00424
00425 dZ *= (1. - bpCor);
00426
00427 return dZ;
00428 }
00429
00430
00431 const SiStripLorentzAngle* SiStripLorentzAngleCalibration::getLorentzAnglesInput()
00432 {
00433
00434
00435
00436
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
00441
00442 if (!siStripLorentzAngleInput_ || siStripLorentzAngleInput_->getLorentzAngles().empty()) {
00443 delete siStripLorentzAngleInput_;
00444 siStripLorentzAngleInput_ = la;
00445 } else {
00446
00447 if (la && !la->getLorentzAngles().empty() &&
00448 la->getLorentzAngles() != siStripLorentzAngleInput_->getLorentzAngles()) {
00449
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_) {
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
00505 id = iterIdValue->first;
00506 value = iterIdValue->second;
00507
00508 auto treeStructIter = treeInfo.find(id);
00509 if (treeStructIter != treeInfo.end()) {
00510 treeStruct = treeStructIter->second;
00511 } else {
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;
00520 }
00521
00522
00523 SiStripLorentzAngle*
00524 SiStripLorentzAngleCalibration::createFromTree(const char *fileName, const char *treeName) const
00525 {
00526
00527
00528 TFile* file = 0;
00529 FILE* testFile = fopen(fileName,"r");
00530 if (testFile) {
00531 fclose(testFile);
00532 file = TFile::Open(fileName, "READ");
00533 }
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 {
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;
00558 return result;
00559 }
00560
00561
00562
00563
00564
00565
00566 #include "Alignment/CommonAlignmentAlgorithm/interface/IntegratedCalibrationPluginFactory.h"
00567
00568 DEFINE_EDM_PLUGIN(IntegratedCalibrationPluginFactory,
00569 SiStripLorentzAngleCalibration, "SiStripLorentzAngleCalibration");