File indexing completed on 2025-12-16 09:20:30
0001 #include "AlignmentTransformation.h"
0002
0003 #include "ActsGeometry.h"
0004 #include "TpcDefs.h"
0005 #include "TrkrDefs.h"
0006
0007 #include <ffamodules/CDBInterface.h>
0008
0009 #include <fun4all/Fun4AllReturnCodes.h>
0010
0011 #include <phool/PHCompositeNode.h>
0012 #include <phool/PHDataNode.h>
0013 #include <phool/PHNode.h>
0014 #include <phool/PHNodeIterator.h>
0015 #include <phool/PHObject.h>
0016 #include <phool/PHTimer.h>
0017 #include <phool/getClass.h>
0018 #include <phool/phool.h>
0019
0020 #include <Acts/Surfaces/PerigeeSurface.hpp>
0021 #include <Acts/Surfaces/PlaneSurface.hpp>
0022 #include <Acts/Surfaces/Surface.hpp>
0023
0024 #include <Eigen/Dense>
0025 #include <Eigen/Geometry>
0026 #include <Eigen/LU>
0027
0028 #include <cmath>
0029 #include <fstream>
0030 #include <sstream>
0031
0032 void AlignmentTransformation::createMap(PHCompositeNode* topNode)
0033 {
0034 localVerbosity = 0;
0035
0036 std::cout << "AlignmentTransformation: use INTT survey geometry = " << use_intt_survey_geometry << std::endl;
0037 std::cout << "AlignmentTransformation: localVerbosity = " << localVerbosity << std::endl;
0038
0039 getNodes(topNode);
0040
0041
0042 if (alignmentTransformationContainer::use_alignment)
0043 {
0044 alignmentTransformationContainer::use_alignment = false;
0045 }
0046
0047
0048 TrkrDefs::hitsetkey hitsetkey = 0;
0049 float alpha = 0.0, beta = 0.0, gamma = 0.0, dx = 0.0, dy = 0.0, dz = 0.0, dgrx = 0.0, dgry = 0.0, dgrz = 0.0;
0050
0051
0052 std::ifstream datafile;
0053 datafile.open(alignmentParamsFile);
0054 if (datafile.is_open())
0055 {
0056 std::cout << "AlignmentTransformation: Reading alignment parameters from disk file: "
0057 << alignmentParamsFile << " localVerbosity = " << localVerbosity << std::endl;
0058 }
0059 else
0060 {
0061 datafile.clear();
0062
0063 alignmentParamsFile = CDBInterface::instance()->getUrl("TRACKINGALIGNMENT");
0064 std::cout << "AlignmentTransformation: Reading alignment parameters from database file: " << alignmentParamsFile << std::endl;
0065 datafile.open(alignmentParamsFile);
0066 }
0067
0068 ActsSurfaceMaps surfMaps = m_tGeometry->maps();
0069 Surface surf;
0070
0071 int linecount = 0;
0072 std::string str;
0073 while( std::getline(datafile, str) )
0074 {
0075
0076 str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](unsigned char ch) {return !std::isspace(ch);}));
0077
0078
0079 if( str.empty() ) { continue; }
0080 if( str.substr(0, 2) == "//" ) {continue;}
0081 if( str.substr(0, 1) == "#" ) {continue;}
0082
0083
0084 std::stringstream ss(str);
0085
0086
0087
0088 std::string dummy;
0089 int count = 0;
0090 while(ss >> dummy)
0091 {
0092 count ++;
0093 }
0094 if(count < 9)
0095 {
0096 std::stringstream str6(str);
0097 str6 >> hitsetkey >> alpha >> beta >> gamma >> dx >> dy >> dz;
0098 if( str6.rdstate()&std::ios::failbit )
0099 {
0100 std::cout << "AlignmentTransformation::createMap - invalid line: " << str << " -------- Exiting" << std::endl;
0101 exit(1);
0102 }
0103 dgrx=0; dgry = 0; dgrz = 0;
0104
0105 if(linecount == 1 && localVerbosity > 0)
0106 {
0107 std::cout << PHWHERE << "The alignment parameters file has only 6 parameters" << std::endl
0108 << " --- setting global rotation parameters to zero!" << std::endl;
0109 }
0110 }
0111 else
0112 {
0113 std::stringstream str9(str);
0114 str9 >> hitsetkey >> alpha >> beta >> gamma >> dx >> dy >> dz >> dgrx >> dgry >> dgrz;
0115 if( str9.rdstate()&std::ios::failbit )
0116 {
0117 std::cout << "AlignmentTransformation::createMap - invalid line: " << str << " -------- Exiting" << std::endl;
0118 exit(1);
0119 }
0120 }
0121
0122 linecount ++;
0123
0124 if(localVerbosity > 0)
0125 {
0126 std::cout << hitsetkey << " " << alpha << " " << beta << " " << gamma << " dx " << dx << " dy " << dy << " dz " << dz
0127 << " dgrx " << dgrx << " dgry " << dgry << " dgrz " << dgrz << std::endl;
0128 }
0129
0130
0131 Eigen::Vector3d sensorAngles(alpha, beta, gamma);
0132 Eigen::Vector3d millepedeTranslation(dx, dy, dz);
0133 Eigen::Vector3d sensorAnglesGlobal(dgrx, dgry, dgrz);
0134
0135 unsigned int trkrId = TrkrDefs::getTrkrId(hitsetkey);
0136
0137 perturbationAngles = Eigen::Vector3d(0.0, 0.0, 0.0);
0138 perturbationAnglesGlobal = Eigen::Vector3d(0.0, 0.0, 0.0);
0139 perturbationTranslation = Eigen::Vector3d(0.0, 0.0, 0.0);
0140
0141 switch( trkrId )
0142 {
0143
0144 case TrkrDefs::mvtxId:
0145 {
0146 if (perturbMVTX)
0147 {
0148 generateRandomPerturbations(mvtxAngleDev, mvtxTransDev);
0149 sensorAngles = sensorAngles + perturbationAngles;
0150 millepedeTranslation = millepedeTranslation + perturbationTranslation;
0151 }
0152
0153 surf = surfMaps.getSiliconSurface(hitsetkey);
0154
0155 Acts::Transform3 transform;
0156 transform = newMakeTransform(surf, millepedeTranslation, sensorAngles, sensorAnglesGlobal, false);
0157
0158 Acts::GeometryIdentifier id = surf->geometryId();
0159
0160 if (localVerbosity)
0161 {
0162 std::cout << " Add transform for MVTX with surface GeometryIdentifier " << id << " trkrid " << trkrId << std::endl;
0163 std::cout << " final mvtx transform:" << std::endl
0164 << transform.matrix() << std::endl;
0165 }
0166 transformMap->addTransform(id, transform);
0167 transformMapTransient->addTransform(id, transform);
0168
0169 break;
0170 }
0171
0172 case TrkrDefs::inttId:
0173 {
0174 if (perturbINTT)
0175 {
0176 generateRandomPerturbations(inttAngleDev, inttTransDev);
0177 sensorAngles = sensorAngles + perturbationAngles;
0178 millepedeTranslation = millepedeTranslation + perturbationTranslation;
0179 }
0180
0181 surf = surfMaps.getSiliconSurface(hitsetkey);
0182
0183 Acts::Transform3 transform;
0184 transform = newMakeTransform(surf, millepedeTranslation, sensorAngles, sensorAnglesGlobal, use_intt_survey_geometry);
0185 Acts::GeometryIdentifier id = surf->geometryId();
0186
0187 if (localVerbosity)
0188 {
0189 std::cout << " Add transform for INTT with surface GeometryIdentifier " << id << " trkrid " << trkrId << std::endl;
0190 }
0191
0192 transformMap->addTransform(id, transform);
0193 transformMapTransient->addTransform(id, transform);
0194 break;
0195 }
0196
0197 case TrkrDefs::tpcId:
0198 {
0199 if (perturbTPC)
0200 {
0201 generateRandomPerturbations(tpcAngleDev, tpcTransDev);
0202 sensorAngles = sensorAngles + perturbationAngles;
0203 millepedeTranslation = millepedeTranslation + perturbationTranslation;
0204 }
0205
0206 unsigned int side = TpcDefs::getSide(hitsetkey);
0207 unsigned int sector = TpcDefs::getSectorId(hitsetkey);
0208 int subsurfkey_min = (1 - side) * 144 + (144 - sector * 12) - 12 - 6;
0209 int subsurfkey_max = subsurfkey_min + 12;
0210
0211
0212 for (int subsurfkey = subsurfkey_min; subsurfkey < subsurfkey_max; subsurfkey++)
0213 {
0214 int sskey = subsurfkey;
0215 if (sskey < 0)
0216 {
0217 sskey += 288;
0218 }
0219
0220 surf = surfMaps.getTpcSurface(hitsetkey, (unsigned int) sskey);
0221
0222 Acts::Transform3 transform;
0223 transform = newMakeTransform(surf, millepedeTranslation, sensorAngles, sensorAnglesGlobal, false);
0224 Acts::GeometryIdentifier id = surf->geometryId();
0225
0226 if (localVerbosity)
0227 {
0228 unsigned int layer = TrkrDefs::getLayer(hitsetkey);
0229 std::cout << " Add transform for TPC with surface GeometryIdentifier " << id << std::endl
0230 << " trkrid " << trkrId << " hitsetkey " << hitsetkey << " layer " << layer << " sector " << sector << " side " << side
0231 << " subsurfkey " << subsurfkey << std::endl;
0232 Acts::Vector3 center = surf->center(m_tGeometry->geometry().getGeoContext()) * 0.1;
0233 std::cout << "Ideal surface center: " << std::endl
0234 << center << std::endl;
0235 std::cout << "transform matrix: " << std::endl
0236 << transform.matrix() << std::endl;
0237 }
0238 transformMap->addTransform(id, transform);
0239 transformMapTransient->addTransform(id, transform);
0240 }
0241
0242 break;
0243 }
0244
0245 case TrkrDefs::micromegasId:
0246 {
0247 if (perturbMM)
0248 {
0249 generateRandomPerturbations(mmAngleDev, mmTransDev);
0250
0251 sensorAngles = sensorAngles + perturbationAngles;
0252 millepedeTranslation = millepedeTranslation + perturbationTranslation;
0253 }
0254 surf = surfMaps.getMMSurface(hitsetkey);
0255
0256 Acts::Transform3 transform;
0257 transform = newMakeTransform(surf, millepedeTranslation, sensorAngles, sensorAnglesGlobal, false);
0258 Acts::GeometryIdentifier id = surf->geometryId();
0259
0260 if (localVerbosity)
0261 {
0262 std::cout << " Add transform for Micromegas with surface GeometryIdentifier " << id << " trkrid " << trkrId << std::endl;
0263 }
0264
0265 transformMap->addTransform(id, transform);
0266 transformMapTransient->addTransform(id, transform);
0267 break;
0268 }
0269
0270 default:
0271 {
0272 std::cout << "AlignmentTransformation::createMap - Invalid Hitsetkey: " << hitsetkey << std::endl;
0273 break;
0274 }
0275
0276 }
0277
0278 }
0279
0280
0281 m_tGeometry->geometry().geoContext = transformMap;
0282
0283 std::cout << " AlignmentTransformation processed " << linecount << " input lines " << std::endl;
0284
0285
0286 alignmentTransformationContainer::use_alignment = true;
0287 }
0288
0289
0290 Acts::Transform3 AlignmentTransformation::newMakeTransform(const Surface& surf, Eigen::Vector3d& millepedeTranslation, Eigen::Vector3d& sensorAngles, Eigen::Vector3d& sensorAnglesGlobal, bool survey)
0291 {
0292
0293 Eigen::Vector3d nullTranslation(0, 0, 0);
0294 Eigen::AngleAxisd a(0, Eigen::Vector3d::UnitX());
0295 Eigen::AngleAxisd b(0, Eigen::Vector3d::UnitY());
0296 Eigen::AngleAxisd g(0, Eigen::Vector3d::UnitZ());
0297 Eigen::Quaternion<double> qnull = g * b * a;
0298 Eigen::Matrix3d nullRotation = qnull.matrix();
0299
0300
0301
0302 Acts::Transform3 actsTransform = surf->transform(m_tGeometry->geometry().getGeoContext());
0303 Eigen::Matrix3d actsRotationPart = actsTransform.rotation();
0304 Eigen::Vector3d actsTranslationPart = actsTransform.translation();
0305
0306
0307 Eigen::AngleAxisd alpha(sensorAngles(0), Eigen::Vector3d::UnitX());
0308 Eigen::AngleAxisd beta(sensorAngles(1), Eigen::Vector3d::UnitY());
0309 Eigen::AngleAxisd gamma(sensorAngles(2), Eigen::Vector3d::UnitZ());
0310 Eigen::Quaternion<double> q = gamma * beta * alpha;
0311 Eigen::Matrix3d millepedeRotation = q.matrix();
0312
0313
0314 Eigen::AngleAxisd grx(sensorAnglesGlobal(0), Eigen::Vector3d::UnitX());
0315 Eigen::AngleAxisd gry(sensorAnglesGlobal(1), Eigen::Vector3d::UnitY());
0316 Eigen::AngleAxisd grz(sensorAnglesGlobal(2), Eigen::Vector3d::UnitZ());
0317 Eigen::Quaternion<double> gqr = grz * gry * grx;
0318 Eigen::Matrix3d millepedeRotationGlobal = gqr.matrix();
0319
0320
0321
0322 Acts::Transform3 mpRotationAffine;
0323 mpRotationAffine.linear() = millepedeRotation;
0324 mpRotationAffine.translation() = nullTranslation;
0325
0326 Acts::Transform3 mpRotationGlobalAffine;
0327 mpRotationGlobalAffine.linear() = millepedeRotationGlobal;
0328 mpRotationGlobalAffine.translation() = nullTranslation;
0329
0330 Acts::Transform3 mpTranslationAffine;
0331 mpTranslationAffine.linear() = nullRotation;
0332 mpTranslationAffine.translation() = millepedeTranslation;
0333
0334 Acts::Transform3 actsRotationAffine;
0335 actsRotationAffine.linear() = actsRotationPart;
0336 actsRotationAffine.translation() = nullTranslation;
0337 Acts::Transform3 actsTranslationAffine;
0338 actsTranslationAffine.linear() = nullRotation;
0339 actsTranslationAffine.translation() = actsTranslationPart;
0340
0341
0342 Acts::Transform3 transform;
0343
0344 if (survey)
0345 {
0346
0347
0348
0349 transform = mpTranslationAffine * mpRotationGlobalAffine * mpRotationAffine;
0350 }
0351 else
0352 {
0353 transform = mpTranslationAffine * mpRotationGlobalAffine * actsTranslationAffine * mpRotationAffine * actsRotationAffine;
0354 }
0355
0356 if (localVerbosity)
0357 {
0358 Acts::Transform3 actstransform = actsTranslationAffine * actsRotationAffine;
0359
0360 std::cout << "newMakeTransform" << std::endl;
0361 std::cout << "Input translation: " << std::endl << millepedeTranslation << std::endl;
0362 std::cout << "Input sensorAngles: " << std::endl << sensorAngles << std::endl;
0363 std::cout << "Input sensorAnglesGlobal: " << std::endl << sensorAnglesGlobal << std::endl;
0364 std::cout << "mpRotationAffine: " << std::endl
0365 << mpRotationAffine.matrix() << std::endl;
0366 std::cout << "millepederotation * acts " << std::endl
0367 << millepedeRotation * actsRotationPart << std::endl;
0368 std::cout << "actsRotationAffine: " << std::endl
0369 << actsRotationAffine.matrix() << std::endl;
0370 std::cout << "actsTranslationAffine: " << std::endl
0371 << actsTranslationAffine.matrix() << std::endl;
0372 std::cout << "full acts transform " << std::endl
0373 << actstransform.matrix() << std::endl;
0374 std::cout << "mpRotationGlobalAffine: " << std::endl
0375 << mpRotationGlobalAffine.matrix() << std::endl;
0376 std::cout << "mpTranslationAffine: " << std::endl
0377 << mpTranslationAffine.matrix() << std::endl;
0378 std::cout << "Overall transform: " << std::endl
0379 << transform.matrix() << std::endl;
0380 std::cout << "overall * idealinv " << std::endl
0381 << (transform * actstransform.inverse()).matrix() << std::endl;
0382 std::cout << "overall - ideal " << std::endl;
0383 for (int test = 0; test < transform.matrix().rows(); test++)
0384 {
0385 for (int test2 = 0; test2 < transform.matrix().cols(); test2++)
0386 {
0387 std::cout << transform(test, test2) - actstransform(test, test2) << ", ";
0388 }
0389 std::cout << std::endl;
0390 }
0391 }
0392
0393 return transform;
0394 }
0395
0396 int AlignmentTransformation::getNodes(PHCompositeNode* topNode)
0397 {
0398 m_tGeometry = findNode::getClass<ActsGeometry>(topNode, "ActsGeometry");
0399 if (!m_tGeometry)
0400 {
0401 std::cout << "ActsGeometry not on node tree. Exiting."
0402 << std::endl;
0403
0404 return Fun4AllReturnCodes::ABORTEVENT;
0405 }
0406
0407 return 0;
0408 }
0409
0410 void AlignmentTransformation::misalignmentFactor(uint8_t layer, const double factor)
0411 {
0412 transformMap->setMisalignmentFactor(layer, factor);
0413 transformMapTransient->setMisalignmentFactor(layer, factor);
0414 }
0415 void AlignmentTransformation::createAlignmentTransformContainer(PHCompositeNode* topNode)
0416 {
0417
0418 PHNodeIterator iter(topNode);
0419
0420 PHCompositeNode* dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
0421 if (!dstNode)
0422 {
0423 std::cerr << "DST node is missing, quitting" << std::endl;
0424 throw std::runtime_error("Failed to find DST node in AlignmentTransformation::createNodes");
0425 }
0426
0427 transformMap = findNode::getClass<alignmentTransformationContainer>(topNode, "alignmentTransformationContainer");
0428 if (!transformMap)
0429 {
0430 transformMap = new alignmentTransformationContainer;
0431 auto node = new PHDataNode<alignmentTransformationContainer>(transformMap, "alignmentTransformationContainer");
0432 dstNode->addNode(node);
0433 }
0434
0435 transformMapTransient = findNode::getClass<alignmentTransformationContainer>(topNode, "alignmentTransformationContainerTransient");
0436 if (!transformMapTransient)
0437 {
0438 transformMapTransient = new alignmentTransformationContainer;
0439 auto node = new PHDataNode<alignmentTransformationContainer>(transformMapTransient, "alignmentTransformationContainerTransient");
0440 dstNode->addNode(node);
0441 }
0442 }
0443
0444 void AlignmentTransformation::generateRandomPerturbations(Eigen::Vector3d angleDev, Eigen::Vector3d transformDev)
0445 {
0446
0447
0448 std::cout << "Generating Random Perturbations..." << std::endl;
0449
0450 if (angleDev(0) != 0)
0451 {
0452 std::normal_distribution<double> distribution(0, angleDev(0));
0453 perturbationAngles(0) = distribution(generator);
0454 }
0455 if (angleDev(1) != 0)
0456 {
0457 std::normal_distribution<double> distribution(0, angleDev(1));
0458 perturbationAngles(1) = distribution(generator);
0459 }
0460 if (angleDev(2) != 0)
0461 {
0462 std::normal_distribution<double> distribution(0, angleDev(2));
0463 perturbationAngles(2) = distribution(generator);
0464 }
0465 if (transformDev(0) != 0)
0466 {
0467 std::normal_distribution<double> distribution(0, transformDev(0));
0468 perturbationTranslation(0) = distribution(generator);
0469 }
0470 if (transformDev(1) != 0)
0471 {
0472 std::normal_distribution<double> distribution(0, transformDev(1));
0473 perturbationTranslation(1) = distribution(generator);
0474 }
0475 if (transformDev(2) != 0)
0476 {
0477 std::normal_distribution<double> distribution(0, transformDev(2));
0478 perturbationTranslation(2) = distribution(generator);
0479 }
0480 if (localVerbosity)
0481 {
0482 std::cout << "randomperturbationAngles" << perturbationAngles << " randomperturbationTrans:" << perturbationTranslation << std::endl;
0483 }
0484 }