ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/CMSSW/Alignment/CommonAlignmentAlgorithm/plugins/SiStripLorentzAngleCalibration.cc
Revision: 1.2
Committed: Wed Sep 5 08:52:41 2012 UTC (12 years, 7 months ago) by flucke
Content type: text/plain
Branch: MAIN
CVS Tags: V04-00-05, V04-00-04
Changes since 1.1: +6 -8 lines
Log Message:
Store float instead of double in temporary trees since that is the value
use by SiStripLorenzAngle class as well.

File Contents

# User Rev Content
1 flucke 1.1 /// \class SiStripLorentzAngleCalibration
2     ///
3     /// Calibration of Lorentz angle (and strip deco mode backplane corrections?)
4     /// for the tracker, integrated in the alignment algorithms.
5     ///
6     /// Note that not all algorithms support this...
7     ///
8     /// \author : Gero Flucke
9     /// date : August 2012
10 flucke 1.2 /// $Revision: 1.1 $
11     /// $Date: 2012/09/05 07:56:27 $
12 flucke 1.1 /// (last update by $Author: flucke $)
13    
14     #include "Alignment/CommonAlignmentAlgorithm/interface/IntegratedCalibrationBase.h"
15    
16     #include "CondCore/DBOutputService/interface/PoolDBOutputService.h"
17     #include "CondFormats/DataRecord/interface/SiStripCondDataRecords.h"
18     #include "CondFormats/SiStripObjects/interface/SiStripLatency.h"
19     #include "CondFormats/SiStripObjects/interface/SiStripLorentzAngle.h"
20    
21     #include "DataFormats/DetId/interface/DetId.h"
22     #include "DataFormats/SiStripDetId/interface/SiStripDetId.h"
23    
24     #include "FWCore/Framework/interface/ESHandle.h"
25     #include "FWCore/Framework/interface/ESWatcher.h"
26     #include "FWCore/MessageLogger/interface/MessageLogger.h"
27     #include "FWCore/ServiceRegistry/interface/Service.h"
28    
29     #include "Geometry/CommonDetUnit/interface/GeomDet.h"
30     #include "MagneticField/Engine/interface/MagneticField.h"
31     #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
32     #include "TrackingTools/TransientTrackingRecHit/interface/TransientTrackingRecHit.h"
33    
34     #include "TTree.h"
35     #include "TFile.h"
36     #include "TString.h"
37    
38     // #include <iostream>
39     #include <vector>
40     #include <sstream>
41    
42     class SiStripLorentzAngleCalibration : public IntegratedCalibrationBase
43     {
44     public:
45     /// Constructor
46     explicit SiStripLorentzAngleCalibration(const edm::ParameterSet &cfg);
47    
48     /// Destructor
49     virtual ~SiStripLorentzAngleCalibration();
50    
51     /// How many parameters does this calibration define?
52     virtual unsigned int numParameters() const;
53    
54     // /// Return all derivatives,
55     // /// default implementation uses other derivatives(..) method,
56     // /// but can be overwritten in derived class for efficiency.
57     // virtual std::vector<double> derivatives(const TransientTrackingRecHit &hit,
58     // const TrajectoryStateOnSurface &tsos,
59     // const edm::EventSetup &setup,
60     // const EventInfo &eventInfo) const;
61    
62     /// Return non-zero derivatives for x- and y-measurements with their indices by reference.
63     /// Return value is their number.
64     virtual unsigned int derivatives(std::vector<ValuesIndexPair> &outDerivInds,
65     const TransientTrackingRecHit &hit,
66     const TrajectoryStateOnSurface &tsos,
67     const edm::EventSetup &setup,
68     const EventInfo &eventInfo) const;
69    
70     /// Setting the determined parameter identified by index,
71     /// should return false if out-of-bounds, true otherwise.
72     virtual bool setParameter(unsigned int index, double value);
73    
74     /// Setting the determined parameter uncertainty identified by index,
75     /// returns false if out-of-bounds, true otherwise.
76     virtual bool setParameterError(unsigned int index, double error);
77    
78     /// Return current value of parameter identified by index.
79     /// Should return 0. if index out-of-bounds.
80     virtual double getParameter(unsigned int index) const;
81    
82     /// Return current value of parameter identified by index.
83     /// Returns 0. if index out-of-bounds or if errors undetermined.
84     virtual double getParameterError(unsigned int index) const;
85    
86     // /// Call at beginning of job:
87     // virtual void beginOfJob(const AlignableTracker *tracker,
88     // const AlignableMuon *muon,
89     // const AlignableExtras *extras);
90    
91     /// Called at end of a the job of the AlignmentProducer.
92     /// Write out determined parameters.
93     virtual void endOfJob();
94    
95     private:
96     /// If called the first time, fill 'siStripLorentzAngleInput_',
97     /// later check that LorentzAngle has not changed.
98     bool checkLorentzAngleInput(const edm::EventSetup &setup, const EventInfo &eventInfo);
99     /// Input LorentzAngle values:
100     /// - either from EventSetup of first call to derivatives(..)
101     /// - or created from files of passed by configuration (i.e. from parallel processing)
102     const SiStripLorentzAngle* getLorentzAnglesInput();
103    
104     /// Determined parameter value for this detId (detId not treated => 0.)
105     /// and the given run.
106     double getParameterForDetId(unsigned int detId, edm::RunNumber_t run) const;
107     /// Index of parameter for given detId (detId not treated => < 0)
108     /// and the given run.
109     int getParameterIndexFromDetId(unsigned int detId, edm::RunNumber_t run) const;
110     /// Total number of IOVs.
111     unsigned int numIovs() const;
112     /// First run of iov (0 if iovNum not treated).
113     edm::RunNumber_t firstRunOfIOV(unsigned int iovNum) const;
114    
115     void writeTree(const SiStripLorentzAngle *lorentzAngle, const char *treeName) const;
116     SiStripLorentzAngle* createFromTree(const char *fileName, const char *treeName) const;
117    
118     const std::string readoutModeName_;
119     int16_t readoutMode_;
120     const bool saveToDB_;
121     const std::string recordNameDBwrite_;
122     const std::string outFileName_;
123     const std::vector<std::string> mergeFileNames_;
124    
125     edm::ESWatcher<SiStripLorentzAngleRcd> watchLorentzAngleRcd_;
126    
127     // const AlignableTracker *alignableTracker_;
128     SiStripLorentzAngle *siStripLorentzAngleInput_;
129     std::vector<double> parameters_;
130     std::vector<double> paramUncertainties_;
131     };
132    
133     //======================================================================
134     //======================================================================
135     //======================================================================
136    
137     SiStripLorentzAngleCalibration::SiStripLorentzAngleCalibration(const edm::ParameterSet &cfg)
138     : IntegratedCalibrationBase(cfg),
139     readoutModeName_(cfg.getParameter<std::string>("readoutMode")),
140     saveToDB_(cfg.getParameter<bool>("saveToDB")),
141     recordNameDBwrite_(cfg.getParameter<std::string>("recordNameDBwrite")),
142     outFileName_(cfg.getParameter<std::string>("treeFile")),
143     mergeFileNames_(cfg.getParameter<std::vector<std::string> >("mergeTreeFiles")),
144     // alignableTracker_(0),
145     siStripLorentzAngleInput_(0)
146     {
147     // SiStripLatency::singleReadOutMode() returns
148     // 1: all in peak, 0: all in deco, -1: mixed state
149     // (in principle one could treat even mixed state APV by APV...)
150     if (readoutModeName_ == "peak") {
151     readoutMode_ = 1;
152     } else if (readoutModeName_ == "deconvolution") {
153     readoutMode_ = 0;
154     } else {
155     throw cms::Exception("BadConfig")
156     << "SiStripLorentzAngleCalibration:\n" << "Unknown mode '"
157     << readoutModeName_ << "', should be 'peak' or 'deconvolution' .\n";
158     }
159    
160     // FIXME: Which granularity, leading to how many parameters?
161     parameters_.resize(2, 0.); // currently two parameters (TIB, TOB), start value 0.
162     paramUncertainties_.resize(2, 0.); // dito for errors
163    
164     edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration" << "Created with name "
165     << this->name() << " for readout mode '" << readoutModeName_
166     << "',\n" << this->numParameters() << " parameters to be determined."
167     << "\nsaveToDB = " << saveToDB_
168     << "\n outFileName = " << outFileName_
169     << "\n N(merge files) = " << mergeFileNames_.size();
170     if (mergeFileNames_.size()) {
171     edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration"
172     << "First file to merge: " << mergeFileNames_[0];
173     }
174     }
175    
176     //======================================================================
177     SiStripLorentzAngleCalibration::~SiStripLorentzAngleCalibration()
178     {
179     // std::cout << "Destroy SiStripLorentzAngleCalibration named " << this->name() << std::endl;
180     delete siStripLorentzAngleInput_;
181     }
182    
183     //======================================================================
184     unsigned int SiStripLorentzAngleCalibration::numParameters() const
185     {
186     return parameters_.size();
187     }
188    
189     //======================================================================
190     unsigned int
191     SiStripLorentzAngleCalibration::derivatives(std::vector<ValuesIndexPair> &outDerivInds,
192     const TransientTrackingRecHit &hit,
193     const TrajectoryStateOnSurface &tsos,
194     const edm::EventSetup &setup,
195     const EventInfo &eventInfo) const
196     {
197     // ugly const-cast:
198     // But it is either only first initialisation or throwing an exception...
199     const_cast<SiStripLorentzAngleCalibration*>(this)->checkLorentzAngleInput(setup, eventInfo);
200    
201     outDerivInds.clear();
202    
203     edm::ESHandle<SiStripLatency> latency;
204     setup.get<SiStripLatencyRcd>().get(latency);
205     const int16_t mode = latency->singleReadOutMode();
206     if(mode == readoutMode_) {
207     if (hit.det()) { // otherwise 'constraint hit' or whatever
208    
209     const int index = this->getParameterIndexFromDetId(hit.det()->geographicalId(),
210     eventInfo.eventId_.run());
211     if (index >= 0) { // otherwise not treated
212     edm::ESHandle<MagneticField> magneticField;
213     setup.get<IdealMagneticFieldRecord>().get(magneticField);
214     const GlobalVector bField(magneticField->inTesla(hit.det()->surface().position()));
215     const LocalVector bFieldLocal(hit.det()->surface().toLocal(bField));
216     const double dZ = hit.det()->surface().bounds().thickness(); // it is a float only...
217     // shift due to LA: dx = tan(LA) * dz = mobility * B_y * dz
218     const double xDerivative = bFieldLocal.y() * dZ; // parameter is mobility!
219     if (xDerivative) { // If field is zero, this is zero: do not return it
220     const Values derivs(xDerivative, 0.); // yDerivative = 0.
221     outDerivInds.push_back(ValuesIndexPair(derivs, index));
222     }
223     }
224     } else {
225     edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::derivatives2"
226     << "Hit without GeomDet, skip!";
227     }
228     } else if (mode != 0 && mode != 1) { // warn only if unknown/mixed mode
229     edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::derivatives3"
230     << "Readout mode is " << mode << ", but looking for "
231     << readoutMode_ << " (" << readoutModeName_ << ").";
232     }
233    
234     return outDerivInds.size();
235     }
236    
237     //======================================================================
238     bool SiStripLorentzAngleCalibration::setParameter(unsigned int index, double value)
239     {
240     if (index >= parameters_.size()) {
241     return false;
242     } else {
243     parameters_[index] = value;
244     return true;
245     }
246     }
247    
248     //======================================================================
249     bool SiStripLorentzAngleCalibration::setParameterError(unsigned int index, double error)
250     {
251     if (index >= paramUncertainties_.size()) {
252     return false;
253     } else {
254     paramUncertainties_[index] = error;
255     return true;
256     }
257     }
258    
259     //======================================================================
260     double SiStripLorentzAngleCalibration::getParameter(unsigned int index) const
261     {
262     // if (index >= parameters_.size()) {
263     // return 0.;
264     // } else {
265     // return parameters_[index];
266     // }
267     return (index >= parameters_.size() ? 0. : parameters_[index]);
268     }
269    
270     //======================================================================
271     double SiStripLorentzAngleCalibration::getParameterError(unsigned int index) const
272     {
273     // if (index >= paramUncertainties_.size()) {
274     // return 0.;
275     // } else {
276     // return paramUncertainties_[index];
277     // }
278     return (index >= paramUncertainties_.size() ? 0. : paramUncertainties_[index]);
279     }
280    
281     // //======================================================================
282     // void SiStripLorentzAngleCalibration::beginOfJob(const AlignableTracker *tracker,
283     // const AlignableMuon */*muon*/,
284     // const AlignableExtras */*extras*/)
285     // {
286     // alignableTracker_ = tracker;
287     // }
288    
289    
290     //======================================================================
291     void SiStripLorentzAngleCalibration::endOfJob()
292     {
293     // loginfo output
294     std::ostringstream out;
295     out << "Parameter results for readout mode '" << readoutModeName_ << "'\n";
296     for (unsigned int iPar = 0; iPar < parameters_.size(); ++iPar) {
297     out << iPar << ": " << parameters_[iPar] << " +- " << paramUncertainties_[iPar] << "\n";
298     }
299     edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration::endOfJob" << out.str();
300    
301     // now write 'input' tree
302     const SiStripLorentzAngle *input = this->getLorentzAnglesInput(); // never NULL
303     const std::string treeName(this->name() + '_' + readoutModeName_ + '_');
304     this->writeTree(input, (treeName + "input").c_str());
305    
306     for (unsigned int iIOV = 0; iIOV < this->numIovs(); ++iIOV) {
307     cond::Time_t firstRunOfIOV = this->firstRunOfIOV(iIOV);
308     SiStripLorentzAngle *output = new SiStripLorentzAngle;
309     // Loop on map of values from input and add (possible) parameter results
310     for (auto iterIdValue = input->getLorentzAngles().begin();
311     iterIdValue != input->getLorentzAngles().end(); ++iterIdValue) {
312     // type of (*iterIdValue) is pair<unsigned int, float>
313     const unsigned int detId = iterIdValue->first; // key of map is DetId
314     // Nasty: putLorentzAngle(..) takes float by reference - not even const reference!
315     float value = iterIdValue->second + this->getParameterForDetId(detId, firstRunOfIOV);
316     output->putLorentzAngle(detId, value); // put result in output
317     }
318    
319     // Write this even for mille jobs?
320     this->writeTree(output, (treeName + Form("result_%lld", firstRunOfIOV)).c_str());
321    
322     if (saveToDB_) { // If requested, write out to DB
323     edm::Service<cond::service::PoolDBOutputService> dbService;
324     if (dbService.isAvailable()) {
325     dbService->writeOne(output, firstRunOfIOV, recordNameDBwrite_.c_str());
326     // no 'delete output;': writeOne(..) took over ownership
327     } else {
328     delete output;
329     edm::LogError("BadConfig") << "@SUB=SiStripLorentzAngleCalibration::endOfJob"
330     << "No PoolDBOutputService available, but saveToDB true!";
331     }
332     } else {
333     delete output;
334     }
335     } // end loop on IOVs
336    
337     }
338    
339     //======================================================================
340     bool SiStripLorentzAngleCalibration::checkLorentzAngleInput(const edm::EventSetup &setup,
341     const EventInfo &eventInfo)
342     {
343     edm::ESHandle<SiStripLorentzAngle> lorentzAngleHandle;
344     if (!siStripLorentzAngleInput_) {
345     setup.get<SiStripLorentzAngleRcd>().get(readoutModeName_, lorentzAngleHandle);
346     siStripLorentzAngleInput_ = new SiStripLorentzAngle(*lorentzAngleHandle);
347     } else {
348     if (watchLorentzAngleRcd_.check(setup)) { // new IOV of input - but how to check peak vs deco?
349     setup.get<SiStripLorentzAngleRcd>().get(readoutModeName_, lorentzAngleHandle);
350     if (lorentzAngleHandle->getLorentzAngles() // but only bad if non-identical values
351     != siStripLorentzAngleInput_->getLorentzAngles()) { // (comparing maps)
352     // FIXME: Could different maps have same content, but different order?
353     // Or 'floating point comparison' problem?
354     throw cms::Exception("BadInput")
355     << "SiStripLorentzAngleCalibration::checkLorentzAngleInput:\n"
356     << "Content of SiStripLorentzAngle changed at run " << eventInfo.eventId_.run()
357     << ", but algorithm expects constant input!\n";
358     return false; // not reached...
359     }
360     }
361     }
362    
363     return true;
364     }
365    
366     //======================================================================
367     const SiStripLorentzAngle* SiStripLorentzAngleCalibration::getLorentzAnglesInput()
368     {
369     // For parallel processing in Millepede II, create SiStripLorentzAngle
370     // from info stored in files of parallel jobs and check that they are identical.
371     // If this job has run on data, still check that LA is identical to the ones
372     // from mergeFileNames_.
373     const std::string treeName(((this->name() + '_') += readoutModeName_) += "_input");
374     for (auto iFile = mergeFileNames_.begin(); iFile != mergeFileNames_.end(); ++iFile) {
375     SiStripLorentzAngle* la = this->createFromTree(iFile->c_str(), treeName.c_str());
376     // siStripLorentzAngleInput_ could be non-null from previous file of this loop
377     // or from checkLorentzAngleInput(..) when running on data in this job as well
378     if (!siStripLorentzAngleInput_ || siStripLorentzAngleInput_->getLorentzAngles().empty()) {
379     delete siStripLorentzAngleInput_; // NULL or empty
380     siStripLorentzAngleInput_ = la;
381     } else {
382     // FIXME: about comparison of maps see comments in checkLorentzAngleInput
383     if (!la->getLorentzAngles().empty() && // single job might not have got events
384     la->getLorentzAngles() != siStripLorentzAngleInput_->getLorentzAngles()) {
385     // Throw exception instead of error?
386     edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
387     << "Different input values from tree " << treeName
388     << " in file " << *iFile << ".";
389    
390     }
391     delete la;
392     }
393     }
394    
395     if (!siStripLorentzAngleInput_) { // no files nor ran on events
396     siStripLorentzAngleInput_ = new SiStripLorentzAngle;
397     edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
398     << "No input, create an empty one ('" << readoutModeName_ << "' mode)!";
399     } else if (siStripLorentzAngleInput_->getLorentzAngles().empty()) {
400     edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
401     << "Empty result ('" << readoutModeName_ << "' mode)!";
402     }
403    
404     return siStripLorentzAngleInput_;
405     }
406    
407     //======================================================================
408     double SiStripLorentzAngleCalibration::getParameterForDetId(unsigned int detId,
409     edm::RunNumber_t run) const
410     {
411     const int index = this->getParameterIndexFromDetId(detId, run);
412    
413     return (index < 0 ? 0. : parameters_[index]);
414     }
415    
416     //======================================================================
417     int SiStripLorentzAngleCalibration::getParameterIndexFromDetId(unsigned int detId,
418     edm::RunNumber_t run) const
419     {
420     // Return the index of the parameter that is used for this DetId.
421     // If this DetId is not treated, return values < 0.
422    
423     // FIXME: Extend to configurable granularity?
424     // Including treatment of run dependence?
425     const SiStripDetId id(detId);
426     if (id.det() == DetId::Tracker) {
427     if (id.subDetector() == SiStripDetId::TIB) return 0;
428     else if (id.subDetector() == SiStripDetId::TOB) return 1;
429     }
430    
431     return -1;
432     }
433    
434     //======================================================================
435     unsigned int SiStripLorentzAngleCalibration::numIovs() const
436     {
437     // FIXME: Needed to include treatment of run dependence!
438     return 1;
439     }
440    
441     //======================================================================
442     edm::RunNumber_t SiStripLorentzAngleCalibration::firstRunOfIOV(unsigned int iovNum) const
443     {
444     // FIXME: Needed to include treatment of run dependence!
445     if (iovNum < this->numIovs()) return 1;
446     else return 0;
447     }
448    
449    
450     //======================================================================
451     void SiStripLorentzAngleCalibration::writeTree(const SiStripLorentzAngle *lorentzAngle,
452     const char *treeName) const
453     {
454     if (!lorentzAngle) return;
455    
456     TFile* file = TFile::Open(outFileName_.c_str(), "UPDATE");
457     if (!file) {
458     edm::LogError("BadConfig") << "@SUB=SiStripLorentzAngleCalibration::writeTree"
459     << "Could not open file '" << outFileName_ << "'.";
460     return;
461     }
462    
463     TTree *tree = new TTree(treeName, treeName);
464     unsigned int id = 0;
465 flucke 1.2 float value = 0.;
466 flucke 1.1 tree->Branch("detId", &id, "detId/i");
467 flucke 1.2 tree->Branch("value", &value, "value/F");
468 flucke 1.1
469     for (auto iterIdValue = lorentzAngle->getLorentzAngles().begin();
470     iterIdValue != lorentzAngle->getLorentzAngles().end(); ++iterIdValue) {
471     // type of (*iterIdValue) is pair<unsigned int, float>
472     id = iterIdValue->first; // key of map is DetId
473     value = iterIdValue->second;
474     tree->Fill();
475     }
476     tree->Write();
477     delete file; // tree vanishes with the file... (?)
478    
479     }
480    
481     //======================================================================
482     SiStripLorentzAngle*
483     SiStripLorentzAngleCalibration::createFromTree(const char *fileName, const char *treeName) const
484     {
485     TTree *tree = 0;
486     TFile* file = TFile::Open(fileName, "READ");
487     if (file) file->GetObject(treeName, tree);
488    
489     SiStripLorentzAngle *result = 0;
490     if (tree) {
491     unsigned int id = 0;
492 flucke 1.2 float value = 0.;
493 flucke 1.1 tree->SetBranchAddress("detId", &id);
494     tree->SetBranchAddress("value", &value);
495    
496     result = new SiStripLorentzAngle;
497     const Long64_t nEntries = tree->GetEntries();
498     for (Long64_t iEntry = 0; iEntry < nEntries; ++iEntry) {
499     tree->GetEntry(iEntry);
500 flucke 1.2 result->putLorentzAngle(id, value);
501 flucke 1.1 }
502     } else {
503     edm::LogError("Alignment") << "@SUB=SiStripLorentzAngleCalibration::createFromTree"
504     << "Could not get TTree '" << treeName << "' from file '"
505     << fileName << "'.";
506     }
507    
508     delete file; // tree will vanish with file
509     return result;
510     }
511    
512    
513     //======================================================================
514     //======================================================================
515     // Plugin definition
516    
517     #include "Alignment/CommonAlignmentAlgorithm/interface/IntegratedCalibrationPluginFactory.h"
518    
519     DEFINE_EDM_PLUGIN(IntegratedCalibrationPluginFactory,
520     SiStripLorentzAngleCalibration, "SiStripLorentzAngleCalibration");