FairRoot/PandaRoot
PndLmdAlignManager.cxx
Go to the documentation of this file.
1 /*
2  * PndLmdAlignManager.cpp
3  *
4  * Created on: May 26, 2015
5  * Author: Roman Klasen, roklasen@uni-mainz.de or klasen@kph.uni-mainz.de
6  */
7 
8 #include <PndLmdAlignManager.h>
9 
10 #include <boost/asio.hpp>
11 #include <boost/asio/io_service.hpp>
12 #include <boost/bind.hpp>
13 #include <boost/lexical_cast.hpp>
14 #include <boost/filesystem.hpp>
15 #include <boost/ref.hpp>
16 #include <boost/regex.hpp>
17 #include <boost/shared_ptr.hpp>
18 #include <boost/thread.hpp>
19 #include <boost/thread/mutex.hpp>
20 
21 #include <functional>
22 #include <fstream>
23 #include <iostream>
24 #include <iomanip>
25 #include <string>
26 #include <vector>
27 
28 #include <PndLmdSensorAligner.h>
29 #include <PndLmdHitPair.h>
30 #include <PndLmdGeometryHelper.h>
31 #include <TChain.h>
32 #include <TClonesArray.h>
33 #include <TFile.h>
34 #include <TGeoMatrix.h>
35 
36 using std::cerr;
37 using std::cout;
38 using std::ifstream;
39 using std::map;
40 using std::ofstream;
41 using std::string;
42 using std::stringstream;
43 using std::vector;
44 
45 boost::mutex incrementMutex;
46 
47 boost::thread_group alignerThreadGroup;
48 
49 void PndLmdAlignManager::resetMTLB(int n, int r, int w) {
50  _i = 0;
51  _n = n;
52  _r = r;
53  _w = w;
54 }
55 
57 
58  incrementMutex.lock();
59  _i++;
60 
61  // Only update r times.
62  if (_n == 0) return;
63  if (_n == 1) return;
64 
65  if (_r > _n) {
66  _r = _n;
67  }
68 
69  //calculate ev / sec every 100000 iterations
70  if (_i % (_n / _r) != 0) {
71  return;
72  }
73 
74  flush(cout);
75 
76  // Calculate the ratio of complete-to-incomplete.
77  float ratio = _i / (float) _n;
78  int c = ratio * _w;
79 
80  // Show the percentage complete.
81  printf("%3d%% [", (int) (ratio * 100));
82 
83  // Show the load bar.
84  for (int x = 0; x < c; x++)
85  printf("=");
86 
87  for (int x = c; x < _w; x++)
88  printf(" ");
89 
90  // ANSI Control codes to go back to the
91  // previous line and clear it.
92  printf("] %d of %d \n\033[F\033[J", _i, _n);
93  incrementMutex.unlock();
94 }
95 
97  init();
98 }
99 
101 
102  _info << "info for aligned areas\n";
103 
104  _zIsTimestamp = true;
105  _allFilesAdded = false;
106  _singleAligner = true;
107  _inCentimeters = false;
108  _enableHelperMatrix = false;
109  _multithreaded = true;
110 
111  _verboseLevel = 0;
112 
113  //int overlapId=-1;
114  fileNames.clear();
115  aligners.clear();
116 
117  //FIXME: remove
118  //helper = &PndLmdGeometryHelper::getInstance();
119 
121  for (size_t i = 0; i < overlapIDs.size(); i++) {
122  int overlapId = overlapIDs[i];
123 
124  PndLmdSensorAligner tempAligner;
125  tempAligner.setOverlapId(overlapId);
126  tempAligner.setZasTimetamp(_zIsTimestamp);
127  tempAligner.setInCentimeters(_inCentimeters);
128  aligners[overlapId] = tempAligner;
129  }
130 
131  // we just started, all aligners are empty
132  for (size_t i = 0; i < overlapIDs.size(); i++) {
133  alignersFull[overlapIDs[i]] = false;
134  }
135 
136  outFilename = "";
137  _firstInitDone = true;
138  std::cout << "PndLmdAlignManager::Init(): Initialization successful." << "\n";
139 }
140 
142 }
143 
144 //bool PndLmdAlignManager::addPair(PndLmdHitPair& pair) {
145 //
146 // bool success = false;
147 // // check if the aligner for that pair is full. if yes, skip this pair.
148 // // do this even before checking that pair, saves on cpu time.
149 // if (alignersFull[pair.getOverlapId()]) {
150 // return false;
151 // }
152 //
153 // pair.check();
154 // if (pair.isSane()) {
155 // success = aligners[pair.getOverlapId()].addSimplePair(pair); //returns true if addPair succeeded
156 // alignersFull[pair.getOverlapId()] = !success; //if addPair failed, the aligner is full
157 // }
158 // else {
159 // cout << "pair is not sane. processing failed.\n";
160 // success = false;
161 // }
162 //
163 // return success;
164 //}
165 
167 
168  bool success = false;
169 
170  // check if the aligner for that pair is full. if yes, skip this pair.
171  // do this even before checking that pair, saves on cpu time.
172  if (alignersFull[pair.getOverlapId()]) {
173  return false;
174  }
175 
176  pair.check();
177  if (pair.isSane()) {
178  success = aligners[pair.getOverlapId()].addSimplePair(pair); //returns true if addPair succeeded
179  alignersFull[pair.getOverlapId()] = !success; //if addPair failed, the aligner is full
180  }
181  else {
182  cout << "pair is not sane. processing failed.\n";
183  }
184 
185  //if pair could not be added, aligner is full. start thread directly.
186  if (!success) {
187  alignerThreadGroup.create_thread(
188  boost::bind(&PndLmdAlignManager::alignOne, this, boost::ref(aligners[pair.getOverlapId()])));
189  }
190 
191  //check if all aligners are done
192  allAlignersDone = true;
193  for (map<int, bool>::iterator it = alignersFull.begin(); it != alignersFull.end(); it++) {
194  if (!(it->second)) {
195  allAlignersDone = false;
196  break;
197  }
198  }
199  if (allAlignersDone) {
200  cout << "all aligners are already full. no further files will be read.\n";
201  }
202 
203  return success;
204 }
205 
207  std::cout << "using " << aligners.size() << " aligners, which have:\n";
208  for (mapIt it = aligners.begin(); it != aligners.end(); it++) {
209  cout << "id: " << it->second.getModuleID() << " has " << it->second.getNoOfPairs() << " pairs."
210  << "\n";
211  }
212 }
213 
215 
216  if (_allFilesAdded) {
217  return false;
218  }
219  else {
220  fileNames.push_back(filename);
221  return true;
222  }
223 }
224 
225 int PndLmdAlignManager::addFilesFromDirectory(std::string directory, int maxFiles) {
226 
227  if (_allFilesAdded) {
228  return fileNames.size();
229  }
230  else {
231  std::vector<string> list;
232  searchFiles(directory, list, ".root", false);
233  for (size_t i = 0; i < list.size(); i++) {
234  fileNames.push_back(list[i]);
235  if ((int) i == maxFiles - 1) { //we use == instead of >= so that maxFiles=0 always chooses all files
236  break;
237  }
238  }
239  _allFilesAdded = true;
240  cout << "looking for files in " << directory << ". choose " << fileNames.size()
241  << " files of maximum of " << maxFiles << ".\n";
242  return fileNames.size();
243  }
244 
245 }
246 
247 //void PndLmdAlignManager::readFiles() {
248 //
249 // _allFilesAdded = true;
250 //
251 // int noOfFiles = fileNames.size();
252 // if (noOfFiles > 0) {
253 // cout << "found " << noOfFiles << " file(s). reading...\n";
254 // }
255 // else {
256 // cout << "no files found. exiting.\n";
257 // exit(0);
258 // }
259 //
260 // TChain* chainPairs = new TChain("pndsim");
261 // for(size_t i=0; i<fileNames.size(); i++){
262 // //cout << files[i] << endl;
263 // if( fileNames[i].find("Lumi_Pairs") != std::string::npos ){
264 // chainPairs->Add(fileNames[i].c_str());
265 // }
266 // }
267 //
268 // //pairs of sensors in LMD coordinates
269 // TClonesArray* hitPairs = new TClonesArray("PndLmdHitPair");
270 // chainPairs->SetBranchAddress("PndLmdHitPair", &hitPairs);
271 // int nEntries = chainPairs->GetEntries();
272 // cout << "HitPairs no of entries: " << nEntries << "\n";
273 //
274 // cout << "Sorting Pairs to Manager...\n";
275 // int totalPairs = 0;
276 // for (int i_event = 0; i_event < nEntries; i_event++) {
277 //
278 // loadBar(i_event, nEntries, 1000, 60);
279 // chainPairs->GetEntry(i_event);
280 // int nPairs = hitPairs->GetEntries();
281 //
282 // //loop over hitPairs per Event
283 // for (int i_Pair = 0; i_Pair < nPairs; i_Pair++) {
284 // PndLmdHitPair* currentPair = (PndLmdHitPair*) hitPairs->At(i_Pair);
285 // addPair(*currentPair);
286 // totalPairs++;
287 // }
288 // }
289 //
290 // cout << "================================ \n";
291 // cout << "total Pairs: " << totalPairs << "\n";
292 // cout << "All done. Running Align Manager. \n";
293 // cout << "================================ \n";
294 //
295 // delete chainPairs;
296 // delete hitPairs;
297 //}
298 
300 
301  _allFilesAdded = true;
302 
303  int noOfFiles = fileNames.size();
304  if (noOfFiles > 0) {
305  cout << "found " << noOfFiles << " file(s). reading...\n";
306  }
307  else {
308  cout << "no files found. exiting.\n";
309  exit(0);
310  }
311 
312  TChain* chainPairs = new TChain("pndsim");
313  for (size_t i = 0; i < fileNames.size(); i++) {
314  //cout << files[i] << endl;
315  if (fileNames[i].find("Lumi_Pairs") != std::string::npos) {
316  chainPairs->Add(fileNames[i].c_str());
317  }
318  }
319 
320  //pairs of sensors in LMD coordinates
321  TClonesArray* hitPairs = new TClonesArray("PndLmdHitPair");
322  chainPairs->SetBranchAddress("PndLmdHitPair", &hitPairs);
323  int nEntries = chainPairs->GetEntries();
324  cout << "HitPairs no of entries: " << nEntries << "\n";
325 
326  cout << "Sorting Pairs to Manager...\n";
327  int totalPairs = 0;
328  for (int i_event = 0; i_event < nEntries; i_event++) {
329 
330  loadBar(i_event, nEntries, 1000, 60);
331  chainPairs->GetEntry(i_event);
332  int nPairs = hitPairs->GetEntries();
333 
334  //loop over hitPairs per Event
335  for (int i_Pair = 0; i_Pair < nPairs; i_Pair++) {
336  PndLmdHitPair* currentPair = (PndLmdHitPair*) hitPairs->At(i_Pair);
337  addPairAndStartAligner(*currentPair);
338  totalPairs++;
339  if (allAlignersDone) {
340  return;
341  }
342  }
343  }
344 
345  cout << "================================ \n";
346  cout << "total Pairs: " << totalPairs << "\n";
347  cout << "All done. Running Align Manager. \n";
348  cout << "================================ \n";
349 
350  delete chainPairs;
351  delete hitPairs;
352 }
353 
355 
356  //start aligner, this can be done concurrently
357  aligner.calculateMatrix();
358 
359  //write binary file only if not already present
360  if (!checkForBinaryFiles()) {
362  }
363  //if binary files already present, then they have been read earlier and we can display a progress bar for the aliners
364  else {
365  incrementMTLB();
366  }
367 
368  //free memory
369  aligner.clearPairs();
370 }
371 
372 void WorkerThread(boost::shared_ptr<boost::asio::io_service> io_service) {
373  io_service->run();
374 }
375 
377 
378  int cur, tot;
379  cur = 0;
380  tot = aligners.size();
381  verbosePrint("aligning single threaded.\n");
382 
383  for (mapIt it = aligners.begin(); it != aligners.end(); it++) {
384  loadBar(cur++, tot, 1000, 60);
385  verbosePrint("calculating matrix.\n");
386  it->second.calculateMatrix();
387  if (it->second.successful()) {
388  verbosePrint("success. getting matrix.\n");
389  Matrix result = it->second.getResultMatrix();
390  string matrixFilename = _matrixOutDir
391  + makeMatrixFileName(it->second.getOverlapId(), _inCentimeters);
392  writeMatrix(result, matrixFilename);
393 
394  _info << "aligner " << it->second.getOverlapId() << ":\n";
395  _info << "no of pairs: " << it->second.getNoOfPairs() << "\n";
396  _info << "\n";
397 
398  }
399  else {
400  cout << "Error: aligner for " << it->second.getOverlapId() << " failed.\n";
401  }
402  }
403 }
404 
406 
407  //new version, multi threaded using thread pool model and boost::asio implementation
408 
409  //shared pointer, since io_services can't be copied
410  boost::shared_ptr<boost::asio::io_service> io_service(new boost::asio::io_service);
411  boost::shared_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(*io_service));
412 
413  //thread group
414  boost::thread_group worker_threads;
415 
416  //make threads, n is number of threads:
417  int nThreads;
418  nThreads = boost::thread::hardware_concurrency();
419 
420  //sometimes hardware_concurrency returns 0 if it can't detect.
421  if (nThreads < 1) {
422  cout << "INFO:: could not detect number of cores. assuming 4.\n";
423  nThreads = 4;
424  }
425 
426  //create worker threads
427  if (_verboseLevel >= 3) cout << "creating threads... ";
428  for (int i = 0; i < nThreads; i++) {
429  worker_threads.create_thread(boost::bind(&WorkerThread, io_service));
430  if (_verboseLevel >= 3) cout << "[" << i << "] ";
431  }
432  if (_verboseLevel >= 3) cout << "done.\nposting work...\n";
433 
434  resetMTLB(aligners.size(), aligners.size(), 60);
435 
436  //post work for threads
437  for (mapIt it = aligners.begin(); it != aligners.end(); it++) {
438 
439  /*
440  * when binding member classes, boost::bind needs the namespace AND the pointer to an object
441  * of that class (here: this-pointer). Also, when using references, use boost::ref()
442  */
443  if (_verboseLevel >= 3) cout << "posting work for aligner " << it->second.getOverlapId() << "... ";
444  io_service->post(boost::bind(&PndLmdAlignManager::alignOne, this, boost::ref(it->second)));
445  if (_verboseLevel >= 3) cout << "done.\n";
446 
447  }
448 
449  //wait for all threads to complete, then and only then write matrices to disk
450  if (_verboseLevel >= 3) cout << "waiting for all threads to complete.\n";
451  work.reset();
452  worker_threads.join_all();
453  if (_verboseLevel >= 3) cout << "all threads done. getting info.\n";
454  for (mapIt it = aligners.begin(); it != aligners.end(); it++) {
455  if (it->second.successful()) {
456  if (_verboseLevel >= 3) cout << "gtting matrix from " << it->second.getOverlapId() << "\n";
457  Matrix result = it->second.getResultMatrix();
458  string matrixFilename = _matrixOutDir
459  + makeMatrixFileName(it->second.getOverlapId(), _inCentimeters);
460 
461  if (!writeMatrix(result, matrixFilename)) {
462  cout << "ERROR: could not write matrix " << matrixFilename << "\n";
463  }
464 
465  _info << "aligner " << it->second.getOverlapId() << ":\n";
466  _info << "no of pairs: " << it->second.getNoOfPairs() << "\n";
467  _info << "\n";
468 
469  if (_verboseLevel >= 3) cout << _info.str() << "\n";
470  }
471  else {
472  cout << "Error: aligner for " << it->second.getOverlapId() << " failed.\n";
473  }
474  }
475 }
476 
478 
480  _enableHelperMatrix = false;
481  cerr << "WARNING! You can't use rotation correction in pixel ICP mode!\n";
482  }
483 
484  checkIOpaths();
485  cout << "starting aligners...\n";
486 
487  if (_multithreaded) {
488  alignMT();
489  }
490  else {
491  alignST();
492  }
493 
494  //write matrix info
495  ofstream of;
496  if (_inCentimeters) {
497  of.open((_matrixOutDir + "/info-cm.txt").c_str());
498  }
499  else {
500  of.open((_matrixOutDir + "/info-px.txt").c_str());
501  }
502 
503  of << _info.str();
504  of.close();
505  cout << "all aligners done.\n";
506 }
507 
508 //these parameters depend on sensor geometry. Use with caution!
509 //Matrix PndLmdAlignManager::transformMatrixFromPixelsToCm(const Matrix &input) {
510 //
511 // /*
512 // * in principle, there should also be a matrix that transforms from sensor active to sensor,
513 // * but inactive area is already accounted for in pixelsX and pixelsY!
514 // */
515 //
516 // //very important, because I still don't know how pixel number corresponds to active area
517 // double pixelsX = 247.5; //guard ring removes part of active area
518 // double pixelsY = 242.5; //guard ring removes part of active area
519 // double pixelSize = 80e-4; //in cm!
520 //
521 // //center of pixel correction matrices
522 // Matrix matrixPixelEdgeToCenter;
523 // Matrix matrixActiveEdgeToCenter;
524 // Matrix matrixScaleActiveToSensor;
525 // Matrix newPixelsToSensorInCm, newSensorInCmToPixels;
526 //
527 // //measure pixels in their center, not their corner
528 // matrixPixelEdgeToCenter = Matrix::eye(4);
529 // matrixPixelEdgeToCenter.val[0][3] += 0.5;
530 // matrixPixelEdgeToCenter.val[1][3] += 0.5;
531 //
532 // //move from sensor edge (pixel [0,0] to center of sensor)
533 // //KEEP IN MIND! This matrix also takes inactive area into account!!
534 // matrixActiveEdgeToCenter = Matrix::eye(4);
535 // matrixActiveEdgeToCenter.val[0][3] -= pixelsX / 2;
536 // matrixActiveEdgeToCenter.val[1][3] -= pixelsY / 2;
537 //
538 // //scaling must be applied after translations
539 // matrixScaleActiveToSensor = Matrix::eye(4);
540 // matrixScaleActiveToSensor.val[0][0] = pixelSize;
541 // matrixScaleActiveToSensor.val[1][1] = pixelSize;
542 //
543 // newPixelsToSensorInCm = matrixScaleActiveToSensor * matrixActiveEdgeToCenter
544 // * matrixPixelEdgeToCenter;
545 // newSensorInCmToPixels = Matrix(newPixelsToSensorInCm);
546 // newSensorInCmToPixels.inv();
547 //
548 // Matrix result;
549 // result = newPixelsToSensorInCm * input * newSensorInCmToPixels;
550 // return result;
551 //}
552 
553 //FIXME: move to AlignQA
554 /*
555  * get transformation matrix of fromSensor -> toSensor (PANDA global reference frame)
556  * this is in cm and IN PANDA GLOBAL.
557  * ATTENTION! set aligned flag true for perfect geometry, else use false!
558  */
559 //Matrix PndLmdAlignManager::getMatrixSensorToSensor(int fromSensor, int toSensor) {
560 //
561 // auto matrixSen1ToLmd = helper->getMatrixSensorToPndGlobal(fromSensor);
562 // auto matrixLmdToSen2 = helper->getMatrixPndGlobalToSensor(toSensor);
563 //
564 // Matrix matSen1ToLmd = castTGeoHMatrixToMatrix(matrixSen1ToLmd);
565 // Matrix matLmdToSen2 = castTGeoHMatrixToMatrix(matrixLmdToSen2);
566 // return matLmdToSen2 * matSen1ToLmd;
567 //}
568 void PndLmdAlignManager::loadBar(int i, int n, int r, int w, std::string message) {
569 
570  // Only update r times.
571  if (n == 0) return;
572  if (n == 1) return;
573 
574  if (r > n) {
575  r = n;
576  }
577 
578  //calculate ev / sec every 100000 iterations
579  if (i % (n / r) != 0) {
580  return;
581  }
582 
583  flush(cout);
584 
585  // Calculate the ratio of complete-to-incomplete.
586  float ratio = i / (float) n;
587  int c = ratio * w;
588 
589  // Show the percentage complete.
590  printf("%3d%% [", (int) (ratio * 100));
591 
592  // Show the load bar.
593  for (int x = 0; x < c; x++)
594  printf("=");
595 
596  for (int x = c; x < w; x++)
597  printf(" ");
598 
599  // ANSI Control codes to go back to the
600  // previous line and clear it.
601  printf("] %s %d of %d \n\033[F\033[J", message.c_str(), i, n);
602 
603 }
604 
606 
607  if (fileNames.size() == 0) {
608  //cout << "no pair files specified, are we using binary data?\n";
609  }
610  for (size_t iFile = 0; iFile < fileNames.size(); iFile++) {
611  if (!boost::filesystem::exists(fileNames[iFile])) {
612  cout << "error opening file:";
613  cout << fileNames[iFile] << "\n";
614  exit(1);
615  }
616  }
617 
618  if (!(outFilename == "")) {
619  boost::filesystem::path outPath(outFilename);
620  if (!boost::filesystem::exists(outPath.parent_path())) {
621  boost::filesystem::create_directories(outPath.parent_path());
622  }
623  }
624 
625  if (!(_matrixOutDir == "")) {
626  if (!boost::filesystem::exists(_matrixOutDir)) {
627  boost::filesystem::create_directories(_matrixOutDir);
628  }
629  }
630 }
631 
632 //FIXME: give reference, not pointer
633 //read contents of specified file, appends to stringstream provided, returns no of lines
634 std::stringstream* PndLmdAlignManager::readFile(std::string filename) {
635 
636  int lines = 0;
637  stringstream *valueStream = new stringstream();
638 
639  ifstream ifs;
640  ifs.open(filename.c_str());
641  if (!ifs.is_open()) {
642  cout << "could not read ";
643  cout << filename;
644  cout << "! aborting." << "\n";
645  return NULL;
646  }
647  string linebuffer; // = new string();
648  while (std::getline(ifs, linebuffer)) {
649  *valueStream << linebuffer << "\n";
650  lines++;
651  }
652  ifs.close();
653 
654  return valueStream;
655 }
656 
658 
659  vector<vector<double> > temp = readFromCSVFile(filename);
660 
661  if (temp.size() < 1) {
662  cout << "warning! can't read matrix from file " << filename << "\n";
663  exit(1);
664  }
665  if (temp[0].size() < 1) {
666  cout << "warning! can't read matrix from file " << filename << "\n";
667  exit(1);
668  }
669 
670  int rows, columns;
671  rows = temp.size();
672  columns = temp[0].size();
673  Matrix result(rows, columns);
674 
675  for (int i = 0; i < rows; i++) {
676  for (int j = 0; j < columns; j++) {
677  result.val[i][j] = temp[i][j];
678  }
679  }
680 
681  return result;
682 }
683 
684 //TODO: Error reporting to log and handling
686 
687  if (!(filename == "")) {
688  boost::filesystem::path outPath(filename);
689  if (!boost::filesystem::exists(outPath.parent_path())) {
690  boost::filesystem::create_directories(outPath.parent_path());
691  }
692  }
693 
694  //cout << "writing matrix " << filename << "\n";
695  std::ofstream outFileStream;
696  outFileStream.open(filename.c_str());
697 
698  if (outFileStream.fail()) {
699  return false;
700  }
701 
702  outFileStream << std::setprecision(16);
703  outFileStream << mat;
704  outFileStream.close();
705  return true;
706 }
707 
708 vector<vector<double> > PndLmdAlignManager::readFromCSVFile(std::string filename) {
709  stringstream *ss;
710  stringstream iss;
711  int i = 0;
712  ss = readFile(filename);
713  string line, token;
714  std::vector<std::vector<double> > data;
715  while (getline(*ss, line)) {
716  iss << line;
717  std::vector<double> tempvec;
718  while (getline(iss, token, ',')) {
719  tempvec.push_back(boost::lexical_cast<double>(token));
720  }
721  data.push_back(tempvec);
722  ++i;
723  iss.clear();
724  }
725  ss->str("");
726  delete ss;
727  iss.str("");
728  return data;
729 }
730 
731 int PndLmdAlignManager::searchFiles(std::string path, std::vector<std::string> &list, std::string detail,
732  bool includeSubDirs) {
733 
734  if (!boost::filesystem::exists(path)) {
735  return 0;
736  }
737  boost::filesystem::directory_iterator iterator(path);
738  for (; iterator != boost::filesystem::directory_iterator(); ++iterator) {
739  if (boost::filesystem::is_directory(iterator->path()) && includeSubDirs) {
740  list.push_back(iterator->path().string());
741  searchFiles(iterator->path().string(), list, detail, includeSubDirs);
742  }
743  else if (boost::filesystem::is_regular_file(iterator->path())) {
744  if (iterator->path().string().find(detail) != std::string::npos) {
745  list.push_back(iterator->path().string());
746  }
747  }
748  }
749  sort(list.begin(), list.end());
750  return list.size();
751 }
752 
753 bool PndLmdAlignManager::mkdir(std::string path) {
754  boost::filesystem::path bpath(path);
755  if (boost::filesystem::exists(bpath)) {
756  return true;
757  }
758  return boost::filesystem::create_directories(bpath);
759 }
760 
761 bool PndLmdAlignManager::exists(std::string path) {
762  boost::filesystem::path bpath(path);
763  if (boost::filesystem::exists(bpath)) {
764  return true;
765  }
766  return false;
767 }
768 
769 //TODO: replcae with c++11 regex instead of boost
770 vector<string> PndLmdAlignManager::findRegex(std::string source, std::string regex) {
771 
772  boost::regex expression(regex);
773  std::string::const_iterator start, end;
774  start = source.begin();
775  end = source.end();
776  boost::match_results<std::string::const_iterator> result;
777  boost::match_flag_type flags = boost::match_default;
778 
779  vector<string> resultStrings;
780 
781  while (regex_search(start, end, result, expression, flags)) {
782  // update search position:
783  start = result[0].second;
784 
785  for (size_t j = 0; j < result.size(); j++) {
786  resultStrings.push_back(boost::lexical_cast<string>(result[j]));
787  }
788 
789  // update flags:
790  flags |= boost::match_prev_avail;
791  flags |= boost::match_not_bob;
792  }
793 
794  return resultStrings;
795 }
796 
797 int PndLmdAlignManager::searchDirectories(std::string curr_directory, std::vector<std::string> &list,
798  bool includeSubDirs) {
799 
800  if (!boost::filesystem::exists(curr_directory)) {
801  return 0;
802  }
803  boost::filesystem::directory_iterator iterator(curr_directory);
804  for (; iterator != boost::filesystem::directory_iterator(); ++iterator) {
805  if (boost::filesystem::is_directory(iterator->path())) {
806  list.push_back(iterator->path().string());
807 
808  //recursively call for sub directories
809  if (includeSubDirs) {
810  searchDirectories(iterator->path().string(), list, includeSubDirs);
811  }
812  }
813  }
814  sort(list.begin(), list.end());
815  return list.size();
816 
817 }
818 
819 void PndLmdAlignManager::setInCentimeters(bool inCentimeters) {
820  _inCentimeters = inCentimeters;
821  for (mapIt it = aligners.begin(); it != aligners.end(); it++) {
822  it->second.setInCentimeters(_inCentimeters);
823  }
824 }
825 
827  _zIsTimestamp = timestamp;
828  for (mapIt it = aligners.begin(); it != aligners.end(); it++) {
829  it->second.setZasTimetamp(_zIsTimestamp);
830  }
831 }
832 
834 
835  //allocate memory for matrix elements
836  double* homogenousMatrix = new double[16];
837  double* finalMatrix = new double[16];
838  matrix.GetHomogenousMatrix(homogenousMatrix);
839 
840  /*
841  * this code was tested on 2016-08-29 and works. The root implementation is still not
842  * according to ROOT documentation, in that the translation parts of a matrix are not
843  * where they should be and sometimes the homogenous coordinate is not set to 1.
844  * This fixes that.
845  *
846  * DO NOT REMOVE THESE COMMENTS!
847  *
848  * When in doubt, refer to the
849  * following code example, that shows where the translations (wrongfully) is:
850  */
851  /*
852 
853  //test tgeohmatrices
854  TGeoHMatrix *h1 = new TGeoHMatrix(TGeoTranslation(1,2,3));
855  TGeoHMatrix *h2 = new TGeoHMatrix();
856  TGeoHMatrix *h3 = new TGeoHMatrix();
857  TGeoHMatrix *h4 = new TGeoHMatrix();
858 
859  h2->SetDx(1.); h2->SetDy(2.); h2->SetDz(3.);
860  double tr[3] = {1.,2.,3.};
861  h3->SetTranslation(tr);
862  const double rot[9] = {0,1,0,-1,0,0,0,0,0};
863  h4->SetRotation(rot);
864 
865  Matrix m1 = castTGeoHMatrixToMatrix(*h1);
866  Matrix m2 = castTGeoHMatrixToMatrix(*h2);
867  Matrix m3 = castTGeoHMatrixToMatrix(*h3);
868  Matrix m4 = castTGeoHMatrixToMatrix(*h4);
869 
870  cout << "m1:\n" << m1 << "\n";
871  cout << "m2:\n" << m2 << "\n";
872  cout << "m3:\n" << m3 << "\n";
873  cout << "m4:\n" << m4 << "\n";
874  */
875 
876  //copy values from the wrong to the correct positions
877  finalMatrix[0] = homogenousMatrix[0];
878  finalMatrix[1] = homogenousMatrix[1];
879  finalMatrix[2] = homogenousMatrix[2];
880  finalMatrix[3] = homogenousMatrix[12];
881  finalMatrix[4] = homogenousMatrix[4];
882  finalMatrix[5] = homogenousMatrix[5];
883  finalMatrix[6] = homogenousMatrix[6];
884  finalMatrix[7] = homogenousMatrix[13];
885  finalMatrix[8] = homogenousMatrix[8];
886  finalMatrix[9] = homogenousMatrix[9];
887  finalMatrix[10] = homogenousMatrix[10];
888  finalMatrix[11] = homogenousMatrix[14];
889  finalMatrix[12] = homogenousMatrix[3];
890  finalMatrix[13] = homogenousMatrix[7];
891  finalMatrix[14] = homogenousMatrix[11];
892  //finalMatrix[15] = homogenousMatrix[15];
893  finalMatrix[15] = 1.0;
894 
895  //create matrix and clean up
896  Matrix result(4, 4, finalMatrix);
897  delete homogenousMatrix;
898  delete finalMatrix;
899  return result;
900 
901 }
902 
904 
905  vector<string> files;
906  searchFiles(_binaryPairFileDirectory, files, "bin", false);
907  int foundFiles = 0;
908 
909  //no binary files at all!
910  if (files.size() == 0) {
911  return false;
912  }
913 
914  string matrixName;
915  bool tempfilefound = false;
916 
917  //check for every ID that should be there if there is a corresponding file
918  for (size_t i = 0; i < overlapIDs.size(); i++) {
919 
920  tempfilefound = false;
922  for (size_t j = 0; j < files.size(); j++) {
923  if (files[j].find(matrixName) != string::npos) {
924  tempfilefound = true;
925  foundFiles++;
926  }
927  }
928 
929  //file not found? then at least one is missing, return false
930  if (!tempfilefound) {
931  return tempfilefound;
932  }
933  }
934  return true;
935 }
936 
938 
939  vector<string> files;
940  searchFiles(_binaryPairFileDirectory, files, "mat", false);
941  int foundFiles = 0;
942 
943  //no binary files at all!
944  if (files.size() == 0) {
945  return false;
946  }
947 
948  string matrixName1, matrixName2;
949  bool tempfilefound = false;
950 
951  //check for every ID that should be there if there is a corresponding file
952  for (size_t i = 0; i < overlapIDs.size(); i++) {
953 
954  //reset counter
955  tempfilefound = false;
956  matrixName1 = makeMatrixFileName(overlapIDs[i], true);
957  matrixName1 = makeMatrixFileName(overlapIDs[i], false);
958 
959  for (size_t j = 0; j < files.size(); j++) {
960  if (files[j].find(matrixName1) != string::npos) {
961  //file is present
962  //cout << "file: " << files[j] << ", id: " << availableIds[i] << "\n";
963  tempfilefound = true;
964  foundFiles++;
965  }
966  }
967 
968  //file not found? then at least one is missing, return false
969  if (!tempfilefound) {
970  return tempfilefound;
971  }
972  }
973  //cout << "found " << foundFiles << "\n";
974  return true;
975 }
976 
977 std::string PndLmdAlignManager::makeBinaryPairFileName(int overlapId, bool incentimeters) {
978  std::stringstream filename;
979  filename << "/pairs-";
980  filename << overlapId;
981  if (incentimeters) {
982  filename << "-cm";
983  }
984  else {
985  filename << "-px";
986  }
987  filename << ".bin";
988  return filename.str();
989 }
990 
991 //std::string PndLmdAlignManager::makeBinaryPairFileName(int sensorOne, int sensorTwo, bool incentimeters) {
992 // int overlapId = helper->getOverlapIdFromSensorIDs(sensorOne, sensorTwo);
993 // return makeBinaryPairFileName(overlapId, incentimeters);
994 //}
995 
996 std::string PndLmdAlignManager::makeMatrixFileName(int overlapId, bool incentimeters) {
997  stringstream matrixName;
998  matrixName << "/m";
999  if (incentimeters) {
1000  matrixName << overlapId << "cm.mat";
1001  }
1002  else {
1003  matrixName << overlapId << "px.mat";
1004  }
1005  return matrixName.str();
1006 }
1007 
1008 // FIXME:
1009 // clean this up, there should be a better way. maybe use the HitLocationInfo structs
1010 //Matrix PndLmdAlignManager::combineCyclicMatrix(int id) {
1011 //
1012 // Matrix result = Matrix::eye(4);
1013 //
1014 // // get id of first sensor on module
1015 // int id1 = (std::floor(id / 10.0)) * 10;
1016 // int id2 = id % 10;
1017 //
1018 // //FIXME: assign matrices, this is shuddy atm.
1019 // string m05f = _matrixOutDir
1020 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 0, id1 + 5), _inCentimeters);
1021 // string m18f = _matrixOutDir
1022 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 1, id1 + 8), _inCentimeters);
1023 // string m28f = _matrixOutDir
1024 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 2, id1 + 8), _inCentimeters);
1025 // string m29f = _matrixOutDir
1026 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 2, id1 + 9), _inCentimeters);
1027 // string m36f = _matrixOutDir
1028 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 3, id1 + 6), _inCentimeters);
1029 // string m37f = _matrixOutDir
1030 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 3, id1 + 7), _inCentimeters);
1031 // string m38f = _matrixOutDir
1032 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 3, id1 + 8), _inCentimeters);
1033 // string m47f = _matrixOutDir
1034 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 4, id1 + 7), _inCentimeters);
1035 // string m49f = _matrixOutDir
1036 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 4, id1 + 9), _inCentimeters);
1037 //
1038 // // we have to know these matrices from external measurements, so it's okay to use misaligned matrices here
1039 // Matrix m01 = getMatrixSensorToSensor(id1, id1 + 1);
1040 // Matrix m56 = getMatrixSensorToSensor(id1 + 5, id1 + 6);
1041 //
1042 // // remember, CM matrices are in LMD local, px matrices are in sensor local!
1043 // // and since we know those from external measurements, we have those
1044 // //FIXME: these functions are missing, so the code does not work right now!
1049 //
1050 // Matrix m05 = readMatrix(m05f);
1051 // Matrix m18 = readMatrix(m18f);
1052 // Matrix m28 = readMatrix(m28f);
1053 // Matrix m29 = readMatrix(m29f);
1054 // Matrix m36 = readMatrix(m36f);
1055 // Matrix m37 = readMatrix(m37f);
1056 // Matrix m38 = readMatrix(m38f);
1057 // Matrix m47 = readMatrix(m47f);
1058 // Matrix m49 = readMatrix(m49f);
1059 //
1060 // // I think all px matrices are inverted
1061 // if (!_inCentimeters) {
1062 // m01.inv();
1063 // m56.inv();
1064 // m05.inv();
1065 // m18.inv();
1066 // m28.inv();
1067 // m29.inv();
1068 // m36.inv();
1069 // m37.inv();
1070 // m38.inv();
1071 // m47.inv();
1072 // m49.inv();
1073 // }
1074 //
1075 // // since we read only correction matrices in cm, we must multiply them
1076 // // with the ideal senToSen to get the complete misaligned senToSen.
1077 // // this isn't cheating as we are only using ideal matrices, which we should
1078 // // always have.
1079 // // but remember, they still live on separate modules.
1080 // if (_inCentimeters) {
1081 //
1082 // Matrix m05ideal = getMatrixSensorToSensor(id1 + 0, id1 + 5);
1083 // Matrix m18ideal = getMatrixSensorToSensor(id1 + 1, id1 + 8);
1084 // Matrix m28ideal = getMatrixSensorToSensor(id1 + 2, id1 + 8);
1085 // Matrix m29ideal = getMatrixSensorToSensor(id1 + 2, id1 + 9);
1086 // Matrix m36ideal = getMatrixSensorToSensor(id1 + 3, id1 + 6);
1087 // Matrix m37ideal = getMatrixSensorToSensor(id1 + 3, id1 + 7);
1088 // Matrix m38ideal = getMatrixSensorToSensor(id1 + 3, id1 + 8);
1089 // Matrix m47ideal = getMatrixSensorToSensor(id1 + 4, id1 + 7);
1090 // Matrix m49ideal = getMatrixSensorToSensor(id1 + 4, id1 + 9);
1091 //
1092 // //FIXME: this is a work around since I can't yet construct the correct misaligned matrices
1102 //
1103 // m05 = m05 * m05ideal;
1104 // m18 = m18 * m18ideal;
1105 // m28 = m28 * m28ideal;
1106 // m29 = m29 * m29ideal;
1107 // m36 = m36 * m36ideal;
1108 // m37 = m37 * m37ideal;
1109 // m38 = m38 * m38ideal;
1110 // m47 = m47 * m47ideal;
1111 // m49 = m49 * m49ideal;
1112 // }
1113 //
1114 // //prepare inverted matrices
1115 // Matrix m10 = m01.inv(m01);
1116 // Matrix m50 = m05.inv(m05);
1117 // Matrix m65 = m56.inv(m56);
1118 // Matrix m81 = m18.inv(m18);
1119 // Matrix m82 = m28.inv(m28);
1120 // Matrix m92 = m29.inv(m29);
1121 // Matrix m63 = m36.inv(m36);
1122 // Matrix m73 = m37.inv(m37);
1123 // Matrix m83 = m38.inv(m38);
1124 // Matrix m74 = m47.inv(m47);
1125 // Matrix m94 = m49.inv(m49);
1126 //
1127 // // case switch, conctruct all cyclic matrices
1128 // switch (id2) {
1129 // case 0:
1130 // result = m10 * m81 * m38 * m63 * m56 * m05; //uses hand-measured matrices m01 and m56
1131 // break;
1132 // case 1:
1133 // result = m81 * m38 * m73 * m47 * m94 * m29 * m82 * m18; //FIXME: change to other path with self inverse
1134 // break;
1135 // case 2:
1136 // result = m82 * m38 * m73 * m47 * m94 * m29;
1137 // break;
1138 // case 3:
1139 // result = m83 * m28 * m92 * m49 * m74 * m37;
1140 // break;
1141 // case 4:
1142 // result = m94 * m29 * m82 * m38 * m73 * m47;
1143 // break;
1144 // case 5:
1145 // result = m05 * m10 * m81 * m38 * m63 * m56; //uses hand-measured matrices m01 and m56
1146 // break;
1147 // case 6:
1148 // result = m36 * m83 * m28 * m92 * m49 * m74 * m37 * m63; //FIXME: change to other path with self inverse
1149 // break;
1150 // case 7:
1151 // result = m47 * m94 * m29 * m82 * m38 * m73;
1152 // break;
1153 // case 8:
1154 // result = m38 * m73 * m47 * m94 * m29 * m82;
1155 // break;
1156 // case 9:
1157 // result = m29 * m82 * m38 * m73 * m47 * m94;
1158 // break;
1159 // }
1160 //
1161 // return result;
1162 //}
1163 
1164 //FIXME: remove
1165 //move to AlignQA
1166 //FIXME holy fuck clean this up
1167 //Matrix PndLmdAlignManager::combineMatrix(int id1, int id2) {
1168 //
1169 // bool success = false;
1170 //
1171 // //FIXME: this is not the correct way to do this. better use the real int values below
1172 // if (id1 > id2) {
1173 // std::swap(id1, id2);
1174 // }
1175 //
1176 // //what module are we on? are id1 and id2 on same module?
1177 // int fhalf, fplane, fmodule, fside;
1178 // int bhalf, bplane, bmodule, bside;
1179 //
1180 // //dimension->Get_sensor_by_id(id1, fhalf, fplane, fmodule, fside, fdie, fsensor);
1181 // //dimension->Get_sensor_by_id(id2, bhalf, bplane, bmodule, bside, bdie, bsensor);
1182 //
1183 // auto infoOne = helper->getHitLocationInfo(id1);
1184 // auto infoTwo = helper->getHitLocationInfo(id2);
1185 //
1186 // fhalf = infoOne.detector_half;
1187 // bhalf = infoTwo.detector_half;
1188 //
1189 // fplane = infoOne.plane;
1190 // bplane = infoTwo.plane;
1191 //
1192 // fmodule = infoOne.module;
1193 // bmodule = infoTwo.module;
1194 //
1195 // if (fhalf != bhalf) {
1196 // cout << "error! id1 and id2 are not on same half!\n";
1197 // success = false;
1198 // }
1199 // if (fplane != bplane) {
1200 // cout << "error! id1 and id2 are not on same plane!\n";
1201 // success = false;
1202 // }
1203 // if (fmodule != bmodule) {
1204 // cout << "error! id1 and id2 are not on same module!\n";
1205 // success = false;
1206 // }
1207 //
1208 // Matrix result;
1209 //
1210 // //at this point, id0 should end in 0, so we can just add numbers
1211 // //FIXME: obviously, this is shuddy and needs fixing
1212 //
1213 // success = true;
1214 //
1215 // //last time, just for safety
1216 // if ((id1 % 10) != 0) {
1217 // cout << "error: id1 is not first sensor on module, something went wrong!\n";
1218 // }
1219 //
1220 // //FIXME: assign matrices, this is shuddy atm. source this out to pndlmddim.
1221 // string m05f = _matrixOutDir
1222 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 0, id1 + 5), _inCentimeters);
1223 // string m18f = _matrixOutDir
1224 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 1, id1 + 8), _inCentimeters);
1225 // string m28f = _matrixOutDir
1226 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 2, id1 + 8), _inCentimeters);
1227 // string m29f = _matrixOutDir
1228 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 2, id1 + 9), _inCentimeters);
1229 // string m36f = _matrixOutDir
1230 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 3, id1 + 6), _inCentimeters);
1231 // string m37f = _matrixOutDir
1232 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 3, id1 + 7), _inCentimeters);
1233 // string m38f = _matrixOutDir
1234 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 3, id1 + 8), _inCentimeters);
1235 // string m47f = _matrixOutDir
1236 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 4, id1 + 7), _inCentimeters);
1237 // string m49f = _matrixOutDir
1238 // + makeMatrixFileName(helper->getOverlapIdFromSensorIDs(id1 + 4, id1 + 9), _inCentimeters);
1239 //
1240 // // we have to know these matrices from external measurements, so it's okay to use misaligned matrices here
1241 // Matrix m01 = getMatrixSensorToSensor(id1, id1 + 1);
1242 // Matrix m56 = getMatrixSensorToSensor(id1 + 5, id1 + 6);
1243 //
1244 // // remember, CM matrices are in LMD local, px matrices are in sensor local!
1245 // // and since we know those from external measurements, we have those
1246 // //FIXME: these functions are missing, so the code does not work right now!
1251 //
1252 // Matrix m05 = readMatrix(m05f);
1253 // Matrix m18 = readMatrix(m18f);
1254 // Matrix m28 = readMatrix(m28f);
1255 // Matrix m29 = readMatrix(m29f);
1256 // Matrix m36 = readMatrix(m36f);
1257 // Matrix m37 = readMatrix(m37f);
1258 // Matrix m38 = readMatrix(m38f);
1259 // Matrix m47 = readMatrix(m47f);
1260 // Matrix m49 = readMatrix(m49f);
1261 //
1262 // // I think all px matrices are inverted
1263 // if (!_inCentimeters) {
1264 // m01.inv();
1265 // m56.inv();
1266 // m05.inv();
1267 // m18.inv();
1268 // m28.inv();
1269 // m29.inv();
1270 // m36.inv();
1271 // m37.inv();
1272 // m38.inv();
1273 // m47.inv();
1274 // m49.inv();
1275 // }
1276 //
1277 // // since we read only correction matrices in cm, we must multiply them
1278 // // with the ideal senToSen to get the complete misaligned senToSen.
1279 // // this isn't cheating as we are only using ideal matrices, which we should
1280 // // always have.
1281 // // but remember, they still live on separate modules.
1282 // if (_inCentimeters) {
1283 //
1284 // Matrix m05ideal = getMatrixSensorToSensor(id1 + 0, id1 + 5);
1285 // Matrix m18ideal = getMatrixSensorToSensor(id1 + 1, id1 + 8);
1286 // Matrix m28ideal = getMatrixSensorToSensor(id1 + 2, id1 + 8);
1287 // Matrix m29ideal = getMatrixSensorToSensor(id1 + 2, id1 + 9);
1288 // Matrix m36ideal = getMatrixSensorToSensor(id1 + 3, id1 + 6);
1289 // Matrix m37ideal = getMatrixSensorToSensor(id1 + 3, id1 + 7);
1290 // Matrix m38ideal = getMatrixSensorToSensor(id1 + 3, id1 + 8);
1291 // Matrix m47ideal = getMatrixSensorToSensor(id1 + 4, id1 + 7);
1292 // Matrix m49ideal = getMatrixSensorToSensor(id1 + 4, id1 + 9);
1293 //
1294 // //FIXME: this is a work around since I can't yet construct the correct misaligned matrices
1304 //
1305 // m05 = m05 * m05ideal;
1306 // m18 = m18 * m18ideal;
1307 // m28 = m28 * m28ideal;
1308 // m29 = m29 * m29ideal;
1309 // m36 = m36 * m36ideal;
1310 // m37 = m37 * m37ideal;
1311 // m38 = m38 * m38ideal;
1312 // m47 = m47 * m47ideal;
1313 // m49 = m49 * m49ideal;
1314 // }
1315 //
1316 // //prepare inverted matrices
1317 // Matrix m10 = m01.inv(m01);
1318 // Matrix m50 = m05.inv(m05);
1319 // Matrix m65 = m56.inv(m56);
1320 // Matrix m81 = m18.inv(m18);
1321 // Matrix m82 = m28.inv(m28);
1322 // Matrix m92 = m29.inv(m29);
1323 // Matrix m63 = m36.inv(m36);
1324 // Matrix m73 = m37.inv(m37);
1325 // Matrix m83 = m38.inv(m38);
1326 // Matrix m74 = m47.inv(m47);
1327 // Matrix m94 = m49.inv(m49);
1328 //
1329 // id2 %= 10;
1330 //
1331 // //finally, if cascade:
1332 // switch (id2) {
1333 // case 0:
1334 // result = m10 * m81 * m38 * m63 * m56 * m05;
1335 // break;
1336 // case 1:
1337 // result = m01;
1338 // break;
1339 // case 2:
1340 // result = m82 * m18 * m01;
1341 // break;
1342 // case 3:
1343 // result = m83 * m18 * m01;
1344 // break;
1345 // case 4:
1346 // result = m94 * m29 * m82 * m18 * m01;
1347 // break;
1348 // case 5:
1349 // result = m05;
1350 // break;
1351 // case 6:
1352 // result = m56 * m05;
1353 // break;
1354 // case 7:
1355 // result = m37 * m63 * m56 * m05;
1356 // break;
1357 // case 8:
1358 // result = m38 * m63 * m56 * m05;
1359 // break;
1360 // case 9:
1361 // result = m29 * m82 * m38 * m63 * m56 * m05;
1362 // break;
1363 // default:
1364 // result = Matrix::eye(4);
1365 // success = false;
1366 // }
1367 //
1368 // //return successfully combined matrix
1369 // if (success) {
1370 // if (!_inCentimeters) {
1371 // result.inv(); //FIXME: this is from a bug where all PX matrices are inverted
1372 // }
1373 // return result;
1374 // }
1375 // //else return unity matrix
1376 // cerr << "warning! could not return matrix " << id1 << " to " << id2
1377 // << "! returning identity matrix!\n";
1378 // return Matrix::eye(4);
1379 //}
1380 
1382 
1383  if (maxPairs > 0) {
1384  for (mapIt it = aligners.begin(); it != aligners.end(); it++) {
1385  it->second.setMaximumNumberOfHitPairs(maxPairs);
1386  }
1387  return;
1388  }
1389  else {
1390  cout << "warning. max pairs must be larger than 0!\n";
1391  return;
1392  }
1393 
1394 }
1395 
1397  cout << "\x1B[2J\x1B[H";
1398 }
1399 
1401 
1402  //start all alignsers that have not already started (i.e. don't have required no of Pairs)
1403  int notStarted = 0;
1404 
1405  cout << "starting remaining aligners.\n";
1406  for (map<int, bool>::iterator it = alignersFull.begin(); it != alignersFull.end(); it++) {
1407  if (!(it->second)) {
1408 
1409  //cout << "starting aligner " << it->first << "\n";
1410  //if pair could not be added, aligner is full. start thread directly.
1411  alignerThreadGroup.create_thread(
1412  boost::bind(&PndLmdAlignManager::alignOne, this, boost::ref(aligners[it->first])));
1413  notStarted++;
1414  }
1415  }
1416  cout << notStarted << " aligners remained.\n";
1417  cout << "jobs queue size : " << alignerThreadGroup.size() << "/360\n";
1418  cout << "waiting for all aligners to finish...";
1419 
1420  //wait for all threads to complete
1421  alignerThreadGroup.join_all();
1422  cout << "done!\n";
1423 
1424  for (mapIt it = aligners.begin(); it != aligners.end(); it++) {
1425  if (it->second.successful()) {
1426 
1427  Matrix result = it->second.getResultMatrix();
1428  string matrixFilename = _matrixOutDir
1429  + makeMatrixFileName(it->second.getOverlapId(), _inCentimeters);
1430 
1431  if (!writeMatrix(result, matrixFilename)) {
1432  cout << "ERROR: could not write matrix " << matrixFilename << "\n";
1433  }
1434 
1435  _info << "aligner " << it->second.getOverlapId() << ":\n";
1436  _info << "no of pairs: " << it->second.getNoOfPairs() << "\n";
1437  _info << "\n";
1438  }
1439  else {
1440  cout << "Error: aligner for " << it->second.getOverlapId() << " failed.\n";
1441  }
1442  }
1443 
1444  //write matrix info
1445  ofstream of;
1446  if (_inCentimeters) {
1447  of.open((_matrixOutDir + "/info-cm.txt").c_str());
1448  }
1449  else {
1450  of.open((_matrixOutDir + "/info-px.txt").c_str());
1451  }
1452 
1453  of << _info.str();
1454  of.close();
1455  cout << "all aligners done.\n";
1456 }
1457 
1458 //FIXME: move to GeometryHelper
1459 //Matrix PndLmdAlignManager::getPixelToCentimeterTransformation() {
1460 //
1461 // Matrix result = Matrix::eye(4);
1462 // Matrix shift = Matrix::eye(4);
1463 // Matrix scale = Matrix::eye(4);
1464 //
1465 // //correct for pixel corner to center
1466 // shift.val[0][3] += 0.5;
1467 // shift.val[1][3] += 0.5;
1468 //
1469 // //shift from corner to center (this considers inactive area!)
1470 // shift.val[0][3] -= (247.5 / 2.0);
1471 // shift.val[1][3] -= (242.5 / 2.0);
1472 //
1473 // //scale for pixel size
1474 // scale.val[0][0] *= 80e-4;
1475 // scale.val[1][1] *= 80e-4;
1476 //
1477 // result = scale * shift;
1478 // return result;
1479 //}
1480 
1482 
1483  if (_binaryPairFileDirectory == "") {
1484  cout << "error: binary pair file directory not set.\n";
1485  cout << "use PndLmdAlignManager::setBinaryPairFileDirectory()\n";
1486  return false;
1487  }
1488 
1489  int cur, tot;
1490  cur = 0;
1491  tot = aligners.size();
1492 
1493  cout << "writing all pairs to binary files\n";
1495 
1496  //maybe do this multithreaded?
1497  for (auto &aligner : aligners) {
1498  loadBar(cur++, tot, 1000, 60);
1499  if (!aligner.second.writePairsToBinary(_binaryPairFileDirectory)) {
1500  return false;
1501  }
1502  }
1503  return true;
1504 }
1505 
1507 
1508  bool success = false;
1509 
1510  if (_binaryPairFileDirectory == "") {
1511  cout << "error: binary pair file directory not set.\n";
1512  cout << "use PndLmdAlignManager::setBinaryPairFileDirectory()\n";
1513  return false;
1514  }
1515 
1516  int cur, tot;
1517  cur = 0;
1518  tot = aligners.size();
1519 
1520  cout << "reading all pairs from binary files\n";
1521 
1522  for (mapIt it = aligners.begin(); it != aligners.end(); it++) {
1523  loadBar(cur++, tot, 1000, 60);
1524  if (!it->second.readPairsFromBinary(_binaryPairFileDirectory)) {
1525  success = false;
1526  }
1527  else {
1528  success = true;
1529  }
1530  }
1531  return success;
1532 }
1533 
1534 void PndLmdAlignManager::verbosePrint(std::string input, int level) {
1535  if (_verboseLevel >= level) {
1536  cout << input;
1537  }
1538 }
1539 
1540 boost::property_tree::ptree PndLmdAlignManager::readConfigFile(std::string filename) {
1541 
1542  //check if file exists
1543  if (!boost::filesystem::exists(filename)) {
1544  cerr << "PndLmdAlignManager::readConfig: ERROR! File " << filename << " not found!\n";
1545  }
1546 
1547  std::ifstream is(filename);
1548  boost::property_tree::ptree root;
1549  try {
1550  boost::property_tree::read_json(is, root);
1551  }
1552  catch (std::exception &e) {
1553  cerr << "PndLmdAlignManager::readConfig: ERROR! Can't parse json file " << filename << ".\n";
1554  }
1555  return root;
1556 }
1557 
1558 bool PndLmdAlignManager::writeConfigFile(boost::property_tree::ptree configTree, std::string filename,
1559  bool replaceExisting) {
1560 
1561  //replace logic
1562 
1563  if (boost::filesystem::exists(filename) && !replaceExisting) {
1564  cerr << "PndLmdAlignManager::writeConfig: Config already exists, will not be replaced.\n";
1565  return false;
1566  }
1567 
1568  boost::filesystem::path outPath(filename);
1569  if (!boost::filesystem::exists(outPath.parent_path())) {
1570  boost::filesystem::create_directories(outPath.parent_path());
1571  }
1572 
1573  std::ofstream os(filename);
1574  boost::property_tree::write_json(os, configTree);
1575  return true;
1576 }
1577 
1579  for (mapIt it = aligners.begin(); it != aligners.end(); it++) {
1580  it->second.clearPairs();
1581  }
1582 }
std::vector< std::string > fileNames
boost::thread_group alignerThreadGroup
bool addFile(std::string filename)
printf("RealTime=%f seconds, CpuTime=%f seconds\n", rtime, ctime)
void setInCentimeters(bool inCentimeters)
static std::vector< int > getAvailableOverlapIDs()
void setInCentimeters(bool inCentimeters)
double r
Definition: RiemannTest.C:14
bool writePairsToBinary(const std::string directory)
Int_t i
Definition: run_full.C:25
PndTransMap * map
Definition: sim_emc_apd.C:99
exit(0)
std::map< int, bool > alignersFull
int n
static int searchDirectories(std::string curr_directory, std::vector< std::string > &list, bool includeSubDirs=true)
static int searchFiles(std::string curr_directory, std::vector< std::string > &list, std::string extension="", bool includeSubDirs=true)
std::map< int, PndLmdSensorAligner > aligners
std::map< int, TString > files
Definition: simubg.C:28
void setOverlapId(Int_t overlapId)
static bool mkdir(std::string path)
static Matrix castTGeoHMatrixToMatrix(const TGeoHMatrix &matrix)
static std::string makeBinaryPairFileName(int overlapId=0, bool incentimeters=true)
Int_t getOverlapId() const
static std::vector< std::string > findRegex(std::string source, std::string regex)
bool isSane() const
Definition: PndLmdHitPair.h:75
void WorkerThread(boost::shared_ptr< boost::asio::io_service > io_service)
void setZasTimestamp(bool timestamp)
void resetMTLB(int n, int r, int w)
static std::stringstream * readFile(std::string filename)
static void loadBar(int current, int total, int resolution, int width, std::string message="")
std::string _binaryPairFileDirectory
std::map< int, PndLmdSensorAligner >::iterator mapIt
void setZasTimetamp(bool value)
static bool writeMatrix(Matrix &mat, std::string filename)
static boost::property_tree::ptree readConfigFile(std::string filename)
Definition: matrix.h:50
static int is
Definition: ranlxd.cxx:374
static std::string makeMatrixFileName(int overlapId=0, bool incentimeters=true)
static bool exists(std::string file)
void verbosePrint(std::string input, int level=3)
Double_t x
static bool writeConfigFile(boost::property_tree::ptree configTree, std::string filename, bool replaceExisting=true)
boost::mutex incrementMutex
std::stringstream _info
static Matrix readMatrix(std::string filename)
TString directory
int addFilesFromDirectory(std::string directory, int maxFiles=0)
void setMaxPairs(int maxPairs)
bool addPairAndStartAligner(PndLmdHitPair &pair)
vector< int > overlapIDs
FLOAT ** val
Definition: matrix.h:138
static std::vector< std::vector< double > > readFromCSVFile(std::string filename)
void alignOne(PndLmdSensorAligner &aligner)
const string filename