Project
Loading...
Searching...
No Matches
GeometryMisAligner.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
50//-----------------------------------------------------------------------------
51
54
55#include "MFTBase/Geometry.h"
56#include "MFTBase/GeometryTGeo.h"
58
60
65
66#include "CCDB/CcdbApi.h"
67#include <TClonesArray.h>
68#include <TGeoMatrix.h>
69#include <TMatrixDSym.h>
70#include <TMath.h>
71#include <TRandom.h>
72#include <Riostream.h>
73#include <vector>
74#include <TFile.h>
75#include <TGeoManager.h>
76#include <TGeoMatrix.h>
77#include <TGeoOverlap.h>
78#include <TGeoPhysicalNode.h>
79#include <fmt/format.h>
80#include "Framework/Logger.h"
81
82using namespace o2::mft;
83using namespace o2::detectors;
84
86
87//______________________________________________________________________________
88GeometryMisAligner::GeometryMisAligner(Double_t cartXMisAligM, Double_t cartXMisAligW, Double_t cartYMisAligM, Double_t cartYMisAligW, Double_t angMisAligM, Double_t angMisAligW) : fUseUni(kFALSE),
89 fUseGaus(kTRUE),
90 fXYAngMisAligFactor(0.0),
91 fZCartMisAligFactor(0.0)
92{
94 for (Int_t i = 0; i < 6; i++) {
95 for (Int_t j = 0; j < 2; j++) {
96 fLadderMisAlig[i][j] = 0.0;
97 fDiskMisAlig[i][j] = 0.0;
98 fSensorMisAlig[i][j] = 0.0;
99 fHalfMisAlig[i][j] = 0.0;
100 }
101 }
102 fLadderMisAlig[0][0] = cartXMisAligM;
103 fLadderMisAlig[0][1] = cartXMisAligW;
104 fLadderMisAlig[1][0] = cartYMisAligM;
105 fLadderMisAlig[1][1] = cartYMisAligW;
106 fLadderMisAlig[5][0] = angMisAligM;
107 fLadderMisAlig[5][1] = angMisAligW;
108}
109
110//______________________________________________________________________________
111GeometryMisAligner::GeometryMisAligner(Double_t cartMisAligM, Double_t cartMisAligW, Double_t angMisAligM, Double_t angMisAligW) : fUseUni(kFALSE),
112 fUseGaus(kTRUE),
113 fXYAngMisAligFactor(0.0),
114 fZCartMisAligFactor(0.0)
115{
117 for (Int_t i = 0; i < 6; i++) {
118 for (Int_t j = 0; j < 2; j++) {
119 fLadderMisAlig[i][j] = 0.0;
120 fDiskMisAlig[i][j] = 0.0;
121 fSensorMisAlig[i][j] = 0.0;
122 fHalfMisAlig[i][j] = 0.0;
123 }
124 }
125 fLadderMisAlig[0][0] = cartMisAligM;
126 fLadderMisAlig[0][1] = cartMisAligW;
127 fLadderMisAlig[1][0] = cartMisAligM;
128 fLadderMisAlig[1][1] = cartMisAligW;
129 fLadderMisAlig[5][0] = angMisAligM;
130 fLadderMisAlig[5][1] = angMisAligW;
131}
132
133//______________________________________________________________________________
134GeometryMisAligner::GeometryMisAligner(Double_t cartMisAlig, Double_t angMisAlig) : fUseUni(kTRUE),
135 fUseGaus(kFALSE),
136 fXYAngMisAligFactor(0.0),
137 fZCartMisAligFactor(0.0)
138{
140 for (Int_t i = 0; i < 6; i++) {
141 for (Int_t j = 0; j < 2; j++) {
142 fLadderMisAlig[i][j] = 0.0;
143 fDiskMisAlig[i][j] = 0.0;
144 fSensorMisAlig[i][j] = 0.0;
145 fHalfMisAlig[i][j] = 0.0;
146 }
147 }
148 fLadderMisAlig[0][1] = cartMisAlig;
149 fLadderMisAlig[1][1] = cartMisAlig;
150 fLadderMisAlig[5][1] = angMisAlig;
151}
152
153//_____________________________________________________________________________
155 fUseGaus(kFALSE),
156 fXYAngMisAligFactor(0.0),
157 fZCartMisAligFactor(0.0)
158{
160 for (Int_t i = 0; i < 6; i++) {
161 for (Int_t j = 0; j < 2; j++) {
162 fLadderMisAlig[i][j] = 0.0;
163 fDiskMisAlig[i][j] = 0.0;
164 fSensorMisAlig[i][j] = 0.0;
165 fHalfMisAlig[i][j] = 0.0;
166 }
167 }
168}
169
170//_________________________________________________________________________
172{
174
175 if (TMath::Abs(factor) > 1.0 && factor > 0.) {
176 fXYAngMisAligFactor = factor;
177 fLadderMisAlig[3][0] = fLadderMisAlig[5][0] * factor; // These lines were
178 fLadderMisAlig[3][1] = fLadderMisAlig[5][1] * factor; // added to keep
179 fLadderMisAlig[4][0] = fLadderMisAlig[5][0] * factor; // backward
180 fLadderMisAlig[4][1] = fLadderMisAlig[5][1] * factor; // compatibility
181 } else {
182 LOG(error) << "Invalid XY angular misalign factor, " << factor;
183 }
184}
185
186//_________________________________________________________________________
188{
190 if (TMath::Abs(factor) < 1.0 && factor > 0.) {
191 fZCartMisAligFactor = factor;
192 fLadderMisAlig[2][0] = fLadderMisAlig[0][0];
193 fLadderMisAlig[2][1] = fLadderMisAlig[0][1] * factor;
194 } else {
195 LOG(error) << "Invalid Z cartesian misalign factor, " << factor;
196 }
197}
198
199//_________________________________________________________________________
200void GeometryMisAligner::GetUniMisAlign(double cartMisAlig[3], double angMisAlig[3], const double lParMisAlig[6][2]) const
201{
203
211
212 cartMisAlig[0] = gRandom->Uniform(-lParMisAlig[0][1] + lParMisAlig[0][0], lParMisAlig[0][0] + lParMisAlig[0][1]);
213 cartMisAlig[1] = gRandom->Uniform(-lParMisAlig[1][1] + lParMisAlig[1][0], lParMisAlig[1][0] + lParMisAlig[1][1]);
214 cartMisAlig[2] = gRandom->Uniform(-lParMisAlig[2][1] + lParMisAlig[2][0], lParMisAlig[2][0] + lParMisAlig[2][1]);
215
216 angMisAlig[0] = gRandom->Uniform(-lParMisAlig[3][1] + lParMisAlig[3][0], lParMisAlig[3][0] + lParMisAlig[3][1]);
217 angMisAlig[1] = gRandom->Uniform(-lParMisAlig[4][1] + lParMisAlig[4][0], lParMisAlig[4][0] + lParMisAlig[4][1]);
218 angMisAlig[2] = gRandom->Uniform(-lParMisAlig[5][1] + lParMisAlig[5][0], lParMisAlig[5][0] + lParMisAlig[5][1]); // degrees
219}
220
221//_________________________________________________________________________
222void GeometryMisAligner::GetGausMisAlign(double cartMisAlig[3], double angMisAlig[3], const double lParMisAlig[6][2]) const
223{
225
233
234 cartMisAlig[0] = gRandom->Gaus(lParMisAlig[0][0], lParMisAlig[0][1]);
235 cartMisAlig[1] = gRandom->Gaus(lParMisAlig[1][0], lParMisAlig[1][1]);
236 cartMisAlig[2] = gRandom->Gaus(lParMisAlig[2][0], lParMisAlig[2][1]);
237
238 angMisAlig[0] = gRandom->Gaus(lParMisAlig[3][0], lParMisAlig[3][1]);
239 angMisAlig[1] = gRandom->Gaus(lParMisAlig[4][0], lParMisAlig[4][1]);
240 angMisAlig[2] = gRandom->Gaus(lParMisAlig[5][0], lParMisAlig[5][1]);
241}
242
243//_________________________________________________________________________
244TGeoCombiTrans GeometryMisAligner::MisAlignSensor() const
245{
254
255 Double_t cartMisAlig[3] = {0, 0, 0};
256 Double_t angMisAlig[3] = {0, 0, 0};
257
258 if (fUseUni) {
259 GetUniMisAlign(cartMisAlig, angMisAlig, fSensorMisAlig);
260 } else {
261 if (!fUseGaus) {
262 LOG(info) << "Neither uniform nor gausian distribution is set! Will use gausian...";
263 }
264 GetGausMisAlign(cartMisAlig, angMisAlig, fSensorMisAlig);
265 }
266
267 TGeoTranslation deltaTrans(cartMisAlig[0], cartMisAlig[1], cartMisAlig[2]);
268 TGeoRotation deltaRot;
269 deltaRot.RotateX(angMisAlig[0]);
270 deltaRot.RotateY(angMisAlig[1]);
271 deltaRot.RotateZ(angMisAlig[2]);
272
273 TGeoCombiTrans deltaTransf(deltaTrans, deltaRot);
274
275 return TGeoCombiTrans(deltaTransf);
276}
277
278//_________________________________________________________________________
279TGeoCombiTrans GeometryMisAligner::MisAlignLadder() const
280{
289
290 Double_t cartMisAlig[3] = {0, 0, 0};
291 Double_t angMisAlig[3] = {0, 0, 0};
292
293 if (fUseUni) {
294 GetUniMisAlign(cartMisAlig, angMisAlig, fLadderMisAlig);
295 } else {
296 if (!fUseGaus) {
297 LOG(info) << "Neither uniform nor gausian distribution is set! Will use gausian...";
298 }
299 GetGausMisAlign(cartMisAlig, angMisAlig, fLadderMisAlig);
300 }
301
302 TGeoTranslation deltaTrans(cartMisAlig[0], cartMisAlig[1], cartMisAlig[2]);
303 TGeoRotation deltaRot;
304 deltaRot.RotateX(angMisAlig[0]);
305 deltaRot.RotateY(angMisAlig[1]);
306 deltaRot.RotateZ(angMisAlig[2]);
307
308 TGeoCombiTrans deltaTransf(deltaTrans, deltaRot);
309
310 return TGeoCombiTrans(deltaTransf);
311}
312
313//_________________________________________________________________________
314TGeoCombiTrans
315 GeometryMisAligner::MisAlignHalf() const
316{
325
326 Double_t cartMisAlig[3] = {0, 0, 0};
327 Double_t angMisAlig[3] = {0, 0, 0};
328
329 if (fUseUni) {
330 GetUniMisAlign(cartMisAlig, angMisAlig, fHalfMisAlig);
331 } else {
332 if (!fUseGaus) {
333 LOG(info) << "Neither uniform nor gausian distribution is set! Will use gausian...";
334 }
335 GetGausMisAlign(cartMisAlig, angMisAlig, fHalfMisAlig);
336 }
337
338 TGeoTranslation deltaTrans(cartMisAlig[0], cartMisAlig[1], cartMisAlig[2]);
339 TGeoRotation deltaRot;
340 deltaRot.RotateX(angMisAlig[0]);
341 deltaRot.RotateY(angMisAlig[1]);
342 deltaRot.RotateZ(angMisAlig[2]);
343
344 TGeoCombiTrans deltaTransf(deltaTrans, deltaRot);
345
346 return TGeoCombiTrans(deltaTransf);
347}
348
349//_________________________________________________________________________
350TGeoCombiTrans
351 GeometryMisAligner::MisAlignDisk() const
352{
361
362 Double_t cartMisAlig[3] = {0, 0, 0};
363 Double_t angMisAlig[3] = {0, 0, 0};
364
365 if (fUseUni) {
366 GetUniMisAlign(cartMisAlig, angMisAlig, fDiskMisAlig);
367 } else {
368 if (!fUseGaus) {
369 LOG(info) << "Neither uniform nor gausian distribution is set! Will use gausian...";
370 }
371 GetGausMisAlign(cartMisAlig, angMisAlig, fDiskMisAlig);
372 }
373
374 TGeoTranslation deltaTrans(cartMisAlig[0], cartMisAlig[1], cartMisAlig[2]);
375 TGeoRotation deltaRot;
376 deltaRot.RotateX(angMisAlig[0]);
377 deltaRot.RotateY(angMisAlig[1]);
378 deltaRot.RotateZ(angMisAlig[2]);
379
380 TGeoCombiTrans deltaTransf(deltaTrans, deltaRot);
381
382 return TGeoCombiTrans(deltaTransf);
383}
384
385//______________________________________________________________________
386bool GeometryMisAligner::matrixToAngles(const double* rot, double& psi, double& theta, double& phi)
387{
392
393 if (std::abs(rot[0]) < 1e-7 || std::abs(rot[8]) < 1e-7) {
394 LOG(error) << "Failed to extract roll-pitch-yall angles!";
395 return false;
396 }
397 psi = std::atan2(-rot[5], rot[8]);
398 theta = std::asin(rot[2]);
399 phi = std::atan2(-rot[1], rot[0]);
400 return true;
401}
402
403//______________________________________________________________________
404void GeometryMisAligner::MisAlign(Bool_t verbose, const std::string& ccdbHost, long tmin, long tmax, const std::string& objectPath, const std::string& fileName)
405{
425
428 std::vector<o2::detectors::AlignParam> lAPvec;
429 LOG(info) << "GeometryMisAligner::MisAlign ";
430
431 double lPsi, lTheta, lPhi = 0.;
432 Int_t nAlignID = 0;
433 Int_t nChip = 0;
434 Int_t nHalf = mGeometryTGeo->getNumberOfHalfs();
435
436 for (Int_t hf = 0; hf < nHalf; hf++) {
437 Int_t nDisks = mGeometryTGeo->getNumberOfDisksPerHalf(hf);
438 // New module transformation
439 TGeoCombiTrans localDeltaTransform = MisAlignHalf();
440 TString sname = mGeometryTGeo->composeSymNameHalf(hf);
441 lAP.setSymName(sname);
442 lAP.setAlignableID(-1);
443 lAP.setLocalParams(localDeltaTransform);
444 lAP.applyToGeometry();
445 lAPvec.emplace_back(lAP);
446
447 for (Int_t dk = 0; dk < nDisks; dk++) {
448 localDeltaTransform = MisAlignDisk();
449 sname = mGeometryTGeo->composeSymNameDisk(hf, dk);
450 lAP.setSymName(sname);
451 lAP.setAlignableID(-1);
452 LOG(debug) << "**** LocalDeltaTransform Disk: " << fmt::format("{} : {} | X: {:+f} Y: {:+f} Z: {:+f} | pitch: {:+f} roll: {:+f} yaw: {:+f}\n", lAP.getSymName(), lAP.getAlignableID(), localDeltaTransform.GetTranslation()[0], localDeltaTransform.GetTranslation()[1], localDeltaTransform.GetTranslation()[2], localDeltaTransform.GetRotationMatrix()[0], localDeltaTransform.GetRotationMatrix()[1], localDeltaTransform.GetRotationMatrix()[2]);
453
454 lAP.setLocalParams(localDeltaTransform);
455 lAP.applyToGeometry();
456 lAPvec.emplace_back(lAP);
457
458 Int_t nLadders = 0;
459 for (Int_t sensor = mGeometryTGeo->getMinSensorsPerLadder(); sensor < mGeometryTGeo->getMaxSensorsPerLadder() + 1; sensor++) {
460 nLadders += mGeometryTGeo->getNumberOfLaddersPerDisk(hf, dk, sensor);
461 }
462
463 for (Int_t lr = 0; lr < nLadders; lr++) { //nLadders
464 localDeltaTransform = MisAlignLadder();
465 sname = mGeometryTGeo->composeSymNameLadder(hf, dk, lr);
466 Int_t nSensorsPerLadder = mGeometryTGeo->getNumberOfSensorsPerLadder(hf, dk, lr);
467 TString path = "/cave_1/barrel_1/" + sname;
468 lAP.setSymName(sname);
469 lAP.setAlignableID(-1);
470 lAP.setLocalParams(localDeltaTransform);
471 lAP.applyToGeometry();
472 lAPvec.emplace_back(lAP);
473
474 for (Int_t sr = 0; sr < nSensorsPerLadder; sr++) {
475 localDeltaTransform = MisAlignSensor();
476 sname = mGeometryTGeo->composeSymNameChip(hf, dk, lr, sr);
477 if (!matrixToAngles(localDeltaTransform.GetRotationMatrix(), lPsi, lTheta, lPhi)) {
478 LOG(error) << "Problem extracting angles from sensor";
479 }
480 lAP.setSymName(sname);
481 Int_t chipID = itsmft::ChipMappingMFT::mChipIDGeoToRO[nChip];
483 lAP.setAlignableID(uid);
484 lAP.setLocalParams(localDeltaTransform);
485 lAP.applyToGeometry();
486 lAPvec.emplace_back(lAP);
487 if (verbose) {
488 LOG(info) << sname << ", nChip: " << nChip << ", uid: " << uid;
489 }
490 nChip++;
491 }
492 }
493 }
494 }
495
496 if (!ccdbHost.empty()) {
497 std::string path = objectPath.empty() ? o2::base::DetectorNameConf::getAlignmentPath(o2::detectors::DetID::MFT) : objectPath;
498 path = "MFT/test_CCDB/MFT"; // testing the ccdb
499 LOGP(info, "Storing alignment object on {}/{}", ccdbHost, path);
501 std::map<std::string, std::string> metadata; // can be empty
502 metadata["test"] = fmt::format("Misalignment objects for DetID:{}", o2::detectors::DetID::MFT);
503 api.init(ccdbHost.c_str()); // or http://localhost:8080 for a local installation
504 // store abitrary user object in strongly typed manner
505 api.storeAsTFileAny(&lAPvec, path, metadata, tmin, tmax);
506 }
507
508 if (!fileName.empty()) {
509 LOGP(info, "Storing MFT alignment in local file {}", fileName);
510 TFile algFile(fileName.c_str(), "recreate");
511 algFile.WriteObjectAny(&lAPvec, "std::vector<o2::detectors::AlignParam>", "alignment");
512 algFile.Close();
513 }
514}
515
516void GeometryMisAligner::SetAlignmentResolution(const TClonesArray* misAlignArray, Int_t rChId, Double_t rChResX, Double_t rChResY, Double_t rDeResX, Double_t rDeResY)
517{
518
519 Int_t chIdMin = (rChId < 0) ? 0 : rChId;
520 Int_t chIdMax = (rChId < 0) ? 9 : rChId;
521 Double_t chResX = (rChResX < 0) ? fDiskMisAlig[0][1] : rChResX;
522 Double_t chResY = (rChResY < 0) ? fDiskMisAlig[1][1] : rChResY;
523 Double_t deResX = (rDeResX < 0) ? fLadderMisAlig[0][1] : rDeResX;
524 Double_t deResY = (rDeResY < 0) ? fLadderMisAlig[1][1] : rDeResY;
525
526 TMatrixDSym mChCorrMatrix(6);
527 mChCorrMatrix[0][0] = chResX * chResX;
528 mChCorrMatrix[1][1] = chResY * chResY;
529
530 TMatrixDSym mDECorrMatrix(6);
531 mDECorrMatrix[0][0] = deResX * deResX;
532 mDECorrMatrix[1][1] = deResY * deResY;
533
534 // not yet implemented
535}
Definition of the base alignment parameters class.
Definition of the Names Generator class.
Definition of the GeometryManager class.
int32_t i
Class describing MFT Geometry Builder.
ClassImp(o2::mft::GeometryMisAligner)
This macro is used to misalign the existing MFT geometry.
Class handling both virtual segmentation and real volumes.
Definition of the Detector class.
uint32_t j
Definition RawData.h:0
std::ostringstream debug
static std::string getAlignmentPath(DId d)
static int getSensID(o2::detectors::DetID detid, int sensid)
int storeAsTFileAny(const T *obj, std::string const &path, std::map< std::string, std::string > const &metadata, long startValidityTimestamp=-1, long endValidityTimestamp=-1, std::vector< char >::size_type maxSize=0) const
Definition CcdbApi.h:157
void init(std::string const &hosts)
Definition CcdbApi.cxx:165
int getAlignableID() const
return alignable entry ID
Definition AlignParam.h:67
void setSymName(const char *m)
set symbolic name of the volume
Definition AlignParam.h:64
const std::string & getSymName() const
return symbolic name of the volume
Definition AlignParam.h:45
bool setLocalParams(double x, double y, double z, double psi, double theta, double phi)
================ methods for setting global delta params from local delta
bool applyToGeometry() const
apply object to geoemetry
void setAlignableID(int id)
set alignable entry ID
Definition AlignParam.h:70
static constexpr ID MFT
Definition DetID.h:71
static constexpr std::array< int, NChips > mChipIDGeoToRO
void SetAlignmentResolution(const TClonesArray *misAlignArray, Int_t chId=-1, Double_t chResX=-1., Double_t chResY=-1., Double_t deResX=-1., Double_t deResY=-1.)
Set alignment resolution to misalign objects to be stored in CCDB.
void SetXYAngMisAligFactor(Double_t factor)
void MisAlign(bool verbose=false, const std::string &ccdbHost="http://ccdb-test.cern.ch:8080", long tmin=0, long tmax=-1, const std::string &objectPath="", const std::string &fileName="MFTAlignment.root")
bool matrixToAngles(const double *rot, double &psi, double &theta, double &phi)
access to geometry details
void SetZCartMisAligFactor(Double_t factor)
static const char * composeSymNameHalf(int hf)
sym name of the half
Int_t getMaxSensorsPerLadder()
Returns the max number of sensors per ladder.
static const char * composeSymNameChip(int hf, int dk, int lr, int chip)
Sym name of the chip in the given half/disk/ladder.
Int_t getNumberOfLaddersPerDisk(Int_t half, Int_t disk, Int_t sensors) const
Returns the number of ladders in each disk of each half.
Int_t getMinSensorsPerLadder()
Returns the min number of sensors per ladder.
Int_t getNumberOfHalfs()
Returns the number of halfs MFT.
Int_t getNumberOfDisksPerHalf(Int_t half) const
Returns the number of disks in each half.
static const char * composeSymNameLadder(int hf, int dk, int lr)
Sym name of the ladder at given half/disk.
static GeometryTGeo * Instance()
Int_t getNumberOfSensorsPerLadder(Int_t half, Int_t disk, Int_t ladder) const
static const char * composeSymNameDisk(int hf, int dk)
Sym name of the disk at given half.
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"