Belle II Software  release-05-02-19
MillepedeAlgorithm.cc
1 
2 #include <alignment/calibration/MillepedeAlgorithm.h>
3 
4 #include <alignment/dataobjects/MilleData.h>
5 #include <alignment/dataobjects/PedeSteering.h>
6 #include <alignment/GlobalLabel.h>
7 #include <alignment/GlobalParam.h>
8 #include <alignment/GlobalTimeLine.h>
9 #include <alignment/Manager.h>
10 #include <alignment/PedeApplication.h>
11 #include <alignment/PedeResult.h>
12 #include <framework/database/EventDependency.h>
13 
14 #include <TH1F.h>
15 #include <TTree.h>
16 
17 using namespace std;
18 using namespace Belle2;
19 using namespace alignment;
20 
21 MillepedeAlgorithm::MillepedeAlgorithm() : CalibrationAlgorithm("MillepedeCollector")
22 {
23  setDescription("Millepede calibration & alignment algorithm");
24 }
25 
27 {
28  auto chisqHist = getObjectPtr<TH1F>("chi2_per_ndf");
29  B2INFO(" Mean of Chi2 / NDF of tracks before calibration: " << chisqHist->GetMean());
30 
31  if (chisqHist->GetEntries() < m_minEntries) {
32  B2INFO("Less than " << m_minEntries << " collected: " << chisqHist->GetEntries() << ". Return c_NotEnoughData.");
33  return c_NotEnoughData;
34  }
35 
36  // Write out binary files from tree and add to steering
38  auto mille = getObjectPtr<MilleData>("mille");
39  for (auto file : mille->getFiles())
40  m_steering.addFile(file);
41 
42  // Run calibration on steering
44 
45  if (!m_pede.success() || !m_result.isValid()) {
46  B2ERROR(m_pede.getExitMessage());
47  return c_Failure;
48  }
49 
50  if (m_result.getNoParameters() == 0) {
51  B2INFO("No parameters to store. Failure.");
52  return c_Failure;
53  }
54 
55 // for (int ipar = 0; ipar < m_result.getNoParameters(); ipar++) {
56 // if (!m_result.isParameterDetermined(ipar)) {
57 // if (!m_result.isParameterFixed(ipar)) {
58 // ++undeterminedParams;
59 // }
60 // }
61 // }
62 
63 
64 
65  // This function gives you the vector of ExpRuns that were requested for this execution only
66  //auto expRuns = getRunList();
67 
68  // Or you can inspect all the input files to get the full RunRange
69  auto expRuns = getRunListFromAllData();
70 
71  int undeterminedParams = 0;
72  double maxCorrectionPull = 0.;
73  int maxCorrectionPullLabel = 0;
74  int nParams = 0;
75  double paramChi2 = 0.;
76 
77  if (m_events.empty()) {
78  GlobalParamVector result(m_components);
79  GlobalParamVector errors(m_components);
80  GlobalParamVector corrections(m_components);
81 
82  GlobalCalibrationManager::initGlobalVector(result);
83  GlobalCalibrationManager::initGlobalVector(errors);
84  GlobalCalibrationManager::initGlobalVector(corrections);
85 
86  // <UniqueID, ElementID, ParameterId, value>
87  std::vector<std::tuple<unsigned short, unsigned short, unsigned short, double>> resultTuple;
88 
89  for (auto& exprun : expRuns) {
90  auto event1 = EventMetaData(1, exprun.second, exprun.first);
91  result.loadFromDB(event1);
92  errors.construct();
93  corrections.construct();
94  break;
95  }
96 
97  // Construct all remaining components not loaded from DB
98  // to easily create new objects not previously in DB :-)
99  // TODO: remove?
100  result.construct();
101 
102 
103 
104  // Loop over all determined parameters:
105  for (int ipar = 0; ipar < m_result.getNoParameters(); ipar++) {
106  if (!m_result.isParameterDetermined(ipar)) {
107  if (!m_result.isParameterFixed(ipar)) {
108  ++undeterminedParams;
109  }
110  continue;
111  }
112 
114  double correction = m_result.getParameterCorrection(ipar);
115  double error = m_result.getParameterError(ipar);
116  double pull = correction / error;
117 
118  ++nParams;
119  paramChi2 += pull * pull;
120 
121  if (fabs(pull) > fabs(maxCorrectionPull)) {
122  maxCorrectionPull = pull;
123  maxCorrectionPullLabel = label.label();
124  }
125 
126  if (m_invertSign) correction = - correction;
127 
128  result.updateGlobalParam(correction, label.getUniqueId(), label.getElementId(), label.getParameterId());
129  errors.setGlobalParam(error, label.getUniqueId(), label.getElementId(), label.getParameterId());
130  corrections.setGlobalParam(correction, label.getUniqueId(), label.getElementId(), label.getParameterId());
131 
132  resultTuple.push_back({label.getUniqueId(), label.getElementId(), label.getParameterId(), correction});
133 
134  }
135 
136  result.postReadFromResult(resultTuple);
137 
138  for (auto object : result.releaseObjects()) {
139  saveCalibration(object);
140  }
141  for (auto object : errors.releaseObjects()) {
142  saveCalibration(object, DataStore::objectName(object->IsA(), "") + "_ERRORS");
143  }
144  for (auto object : corrections.releaseObjects()) {
145  saveCalibration(object, DataStore::objectName(object->IsA(), "") + "_CORRECTIONS");
146  }
147  } else {
148 
149  GlobalParamVector gpv(m_components);
150  GlobalCalibrationManager::initGlobalVector(gpv);
151  GlobalLabel label_system;
152 
153  alignment::timeline::GlobalParamTimeLine timeline(m_events, label_system, gpv);
154  alignment::timeline::GlobalParamTimeLine timeline_errors(m_events, label_system, gpv);
155  alignment::timeline::GlobalParamTimeLine timeline_corrections(m_events, label_system, gpv);
156  timeline.loadFromDB();
157  timeline_corrections.loadFromDB();
158  timeline_errors.loadFromDB();
159 
160  // Loop over all determined parameters:
161  for (int ipar = 0; ipar < m_result.getNoParameters(); ipar++) {
162  if (!m_result.isParameterDetermined(ipar)) {
163  if (!m_result.isParameterFixed(ipar)) {
164  ++undeterminedParams;
165  }
166  continue;
167  }
168 
170  double correction = m_result.getParameterCorrection(ipar);
171  double error = m_result.getParameterError(ipar);
172  double pull = correction / error;
173 
174  ++nParams;
175  paramChi2 += pull * pull;
176 
177  if (fabs(pull) > fabs(maxCorrectionPull)) {
178  maxCorrectionPull = pull;
179  maxCorrectionPullLabel = label.label();
180  }
181 
182  if (m_invertSign) correction = - correction;
183 
184  timeline.updateGlobalParam(label, correction);
185  timeline_errors.updateGlobalParam(label, error, true);
186  timeline_corrections.updateGlobalParam(label, correction, true);
187  }
188 
189  //TODO: if data do not cover all parts of timeline, this will lead to memory leak for
190  // objects not being saved in DB -> delete them here
191  auto objects = timeline.releaseObjects();
192  for (auto iov_obj : objects) {
193  if (iov_obj.second && !iov_obj.first.overlap(getIovFromAllData()).empty()) {
194  if (auto evdep = dynamic_cast<EventDependency*>(iov_obj.second)) {
195  saveCalibration(iov_obj.second, DataStore::objectName(evdep->getAnyObject()->IsA(), ""),
196  iov_obj.first.overlap(getIovFromAllData()));
197  } else {
198  saveCalibration(iov_obj.second, DataStore::objectName(iov_obj.second->IsA(), ""), iov_obj.first.overlap(getIovFromAllData()));
199  }
200  } else {
201  if (iov_obj.second) delete iov_obj.second;
202  }
203  }
204 
205  auto objects_errors = timeline_errors.releaseObjects();
206  for (auto iov_obj : objects_errors) {
207  if (iov_obj.second && !iov_obj.first.overlap(getIovFromAllData()).empty()) {
208  if (auto evdep = dynamic_cast<EventDependency*>(iov_obj.second)) {
209  saveCalibration(iov_obj.second, DataStore::objectName(evdep->getAnyObject()->IsA(), "") + "_ERRORS",
210  iov_obj.first.overlap(getIovFromAllData()));
211  } else {
212  saveCalibration(iov_obj.second, DataStore::objectName(iov_obj.second->IsA(), "") + "_ERRORS",
213  iov_obj.first.overlap(getIovFromAllData()));
214  }
215  } else {
216  if (iov_obj.second) delete iov_obj.second;
217  }
218  }
219 
220  auto objects_corrections = timeline_corrections.releaseObjects();
221  for (auto iov_obj : objects_corrections) {
222  if (iov_obj.second && !iov_obj.first.overlap(getIovFromAllData()).empty()) {
223  if (auto evdep = dynamic_cast<EventDependency*>(iov_obj.second)) {
224  saveCalibration(iov_obj.second, DataStore::objectName(evdep->getAnyObject()->IsA(), "") + "_CORRECTIONS",
225  iov_obj.first.overlap(getIovFromAllData()));
226  } else {
227  saveCalibration(iov_obj.second, DataStore::objectName(iov_obj.second->IsA(), "") + "_CORRECTIONS",
228  iov_obj.first.overlap(getIovFromAllData()));
229  }
230  } else {
231  if (iov_obj.second) delete iov_obj.second;
232  }
233  }
234 
235  }
236 
237  if (undeterminedParams) {
238  B2WARNING("There are " << undeterminedParams << " undetermined parameters.");
240  B2WARNING("Not enough data for calibration.");
241  return c_NotEnoughData;
242  }
243  }
244 
245  //commit();
246 
247  if (paramChi2 / nParams > 1. || fabs(maxCorrectionPull) > 10.) {
248  B2INFO("Largest correction/error is " << maxCorrectionPull << " for parameter with label " << maxCorrectionPullLabel);
249  B2INFO("Parameter corrections Chi2/NDF, e.g. sum[(correction/error)^2]/#params = " << paramChi2 / nParams
250  << " = " << paramChi2 << " / " << nParams << " > 1.");
251 
252  B2INFO("Requesting iteration.");
253  return c_Iterate;
254  }
255 
256  return c_OK;
257 }
258 
260 {
261  // Clear list of binaries in steering
263 
264  // Temp file name
265  const std::string milleFileName("gbl-data.mille");
266 
267  // For no entries, no binary file is created
268  auto gblDataTree = getObjectPtr<TTree>("GblDataTree");
269  if (!gblDataTree) {
270  B2WARNING("No GBL data tree object in collected data.");
271  return;
272  } else if (!gblDataTree->GetEntries()) {
273  B2WARNING("No trajectories in GBL data tree.");
274  return;
275  }
276 
277  // Create new mille binary
278  auto milleBinary = new gbl::MilleBinary(milleFileName);
279 
280  // Containers for GBL data
281  double aValue(0.);
282  double aErr(0.);
283  std::vector<unsigned int>* indLocal;
284  std::vector<double>* derLocal;
285  std::vector<int>* labGlobal;
286  std::vector<double>* derGlobal;
287 
288  // Read vectors of GblData from tree branch
289  std::vector<gbl::GblData>* currentGblData = new std::vector<gbl::GblData>();
290  gblDataTree->SetBranchAddress("GblData", &currentGblData);
291 
292  B2INFO("Writing Millepede binary files...");
293  for (unsigned int iRecord = 0; iRecord < gblDataTree->GetEntries(); ++iRecord) {
294  gblDataTree->GetEntry(iRecord);
295 
296  if (!currentGblData)
297  continue;
298 
299  for (gbl::GblData& theData : *currentGblData) {
300  theData.getAllData(aValue, aErr, indLocal, derLocal, labGlobal,
301  derGlobal);
302  milleBinary->addData(aValue, aErr, *indLocal, *derLocal, *labGlobal,
303  *derGlobal);
304  }
305  milleBinary->writeRecord();
306  }
307  // Closes the file
308  delete milleBinary;
309  B2INFO("Millepede binary files written.");
310 
311  // Add binary to steering
312  m_steering.addFile(milleFileName);
313 }
Belle2::alignment::PedeResult::isValid
bool isValid()
Was the object initialized properly from a result file?
Definition: PedeResult.h:44
Belle2::MillepedeAlgorithm::m_pede
alignment::PedeApplication m_pede
The Pede application (unsuccesfull until execution)
Definition: MillepedeAlgorithm.h:128
Belle2::PedeSteering::addFile
void addFile(std::string filename, double weight=1.)
Add a file (optionally with weight) to list of binary files.
Definition: PedeSteering.cc:62
Belle2::alignment::timeline::GlobalParamTimeLine
Convenient class to automatically create payloads from allowed time depedence of parameter,...
Definition: GlobalTimeLine.h:156
Belle2::CalibrationAlgorithm::saveCalibration
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
Definition: CalibrationAlgorithm.cc:290
Belle2::MillepedeAlgorithm::m_minEntries
int m_minEntries
Minimum entries collected - report NotEnoughData for less.
Definition: MillepedeAlgorithm.h:139
Belle2::alignment::PedeResult::isParameterFixed
bool isParameterFixed(unsigned int parameterIndex)
Is parameter at given index fixed?
Definition: PedeResult.cc:153
Belle2::CalibrationAlgorithm::c_Iterate
@ c_Iterate
Needs iteration =1 in Python.
Definition: CalibrationAlgorithm.h:52
Belle2::alignment::timeline::GlobalParamTimeLine::releaseObjects
std::vector< std::pair< IntervalOfValidity, TObject * > > releaseObjects()
Release all the objects (you become the owner!) for DB storage.
Definition: GlobalTimeLine.cc:289
Belle2::alignment::PedeResult::getParameterCorrection
double getParameterCorrection(unsigned int parameterIndex)
Get determined correction of parameter at index.
Definition: PedeResult.cc:138
Belle2::MillepedeAlgorithm::m_invertSign
bool m_invertSign
Add (true) or subtract (false) corrections?
Definition: MillepedeAlgorithm.h:122
Belle2::CalibrationAlgorithm::c_OK
@ c_OK
Finished successfuly =0 in Python.
Definition: CalibrationAlgorithm.h:51
Belle2::MillepedeAlgorithm::m_events
std::vector< EventMetaData > m_events
The events at which payloads can change for time-dep calibration (translation from time IDs (aka cont...
Definition: MillepedeAlgorithm.h:133
Belle2::CalibrationAlgorithm::setDescription
void setDescription(const std::string &description)
Set algorithm description (in constructor)
Definition: CalibrationAlgorithm.h:331
Belle2::GlobalLabel
Class to convert to/from global labels for Millepede II to/from detector & parameter identificators.
Definition: GlobalLabel.h:51
Belle2::alignment::PedeResult::getParameterLabel
unsigned int getParameterLabel(unsigned int parameterIndex)
Get label of parameter at index.
Definition: PedeResult.cc:133
Belle2::alignment::PedeResult::isParameterDetermined
bool isParameterDetermined(unsigned int parameterIndex)
Is parameter at given index determined?
Definition: PedeResult.cc:158
Belle2::EventDependency
Class for handling changing conditions as a function of event number.
Definition: EventDependency.h:32
Belle2::MillepedeAlgorithm::m_result
alignment::PedeResult m_result
The result (invalid until execution)
Definition: MillepedeAlgorithm.h:126
Belle2::MillepedeAlgorithm::calibrate
virtual EResult calibrate() override
Run algo on data.
Definition: MillepedeAlgorithm.cc:26
Belle2::CalibrationAlgorithm::getIovFromAllData
IntervalOfValidity getIovFromAllData() const
Get the complete IoV from inspection of collected data.
Definition: CalibrationAlgorithm.cc:318
Belle2::MillepedeAlgorithm::result
alignment::PedeResult & result()
Get the result (invalid until executed) to get parameters etc.
Definition: MillepedeAlgorithm.h:48
Belle2::MillepedeAlgorithm::m_steering
PedeSteering m_steering
The steering with commands.
Definition: MillepedeAlgorithm.h:124
Belle2::CalibrationAlgorithm::getRunListFromAllData
std::vector< Calibration::ExpRun > getRunListFromAllData() const
Get the complete list of runs from inspection of collected data.
Definition: CalibrationAlgorithm.cc:311
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::alignment::timeline::GlobalParamTimeLine::updateGlobalParam
void updateGlobalParam(GlobalLabel label, double correction, bool resetParam=false)
Add a correction to any payload's parameter in the timeline.
Definition: GlobalTimeLine.cc:262
Belle2::CalibrationAlgorithm::c_Failure
@ c_Failure
Failed =3 in Python.
Definition: CalibrationAlgorithm.h:54
gbl::GblData
Data (block) for independent scalar measurement.
Definition: GblData.h:55
Belle2::alignment::PedeResult::getParameterError
double getParameterError(unsigned int parameterIndex)
Get correction error of parameter at index.
Definition: PedeResult.cc:143
Belle2::MillepedeAlgorithm::prepareMilleBinary
void prepareMilleBinary()
Write out binary files from data in tree with GBL data to be used by Millepede and add them to steeri...
Definition: MillepedeAlgorithm.cc:259
Belle2::CalibrationAlgorithm::EResult
EResult
The result of calibration.
Definition: CalibrationAlgorithm.h:50
Belle2::alignment::timeline::GlobalParamTimeLine::loadFromDB
void loadFromDB()
Load every single payload with the content in database at its corresponding event (when it should sta...
Definition: GlobalTimeLine.cc:238
Belle2::MillepedeAlgorithm::m_ignoreUndeterminedParams
bool m_ignoreUndeterminedParams
Report failure(false) or success (true) even if some parameters could not be determined.
Definition: MillepedeAlgorithm.h:130
Belle2::EventMetaData
Store event, run, and experiment numbers.
Definition: EventMetaData.h:43
Belle2::CalibrationAlgorithm::c_NotEnoughData
@ c_NotEnoughData
Needs more data =2 in Python.
Definition: CalibrationAlgorithm.h:53
Belle2::alignment::PedeApplication::success
bool success()
Was Pede successfull (can the result be used)?
Definition: PedeApplication.h:44
Belle2::MillepedeAlgorithm::m_components
std::vector< std::string > m_components
Components (BeamSpot...) to calibrate or empty for all available in data.
Definition: MillepedeAlgorithm.h:120
Belle2::alignment::PedeApplication::calibrate
PedeResult calibrate(PedeSteering &steering)
Run Pede and return full result with parameter corrections.
Definition: PedeApplication.cc:53
Belle2::CalibrationAlgorithm
Base class for calibration algorithms.
Definition: CalibrationAlgorithm.h:47
Belle2::DataStore::objectName
static std::string objectName(const TClass *t, const std::string &name)
Return the storage name for an object of the given TClass and name.
Definition: DataStore.cc:151
Belle2::alignment::PedeApplication::getExitMessage
std::string getExitMessage() const
Returns the Pede exit message (from millepede.end file)
Definition: PedeApplication.h:52
gbl::MilleBinary
Millepede-II (binary) record.
Definition: MilleBinary.h:68
Belle2::PedeSteering::clearFiles
void clearFiles()
Clear list of files.
Definition: PedeSteering.h:46
Belle2::alignment::PedeResult::getNoParameters
int getNoParameters() const
Get number of parameters in result (for looping over)
Definition: PedeResult.h:48