ATLAS Offline Software
Loading...
Searching...
No Matches
runMdtGeoComparison.cxx File Reference
#include <GeoPrimitives/GeoPrimitivesHelpers.h>
#include <GeoPrimitives/GeoPrimitivesToStringConverter.h>
#include "GeoModelHelpers/TransformToStringConverter.h"
#include <MuonCablingData/MdtCablingData.h>
#include <MuonReadoutGeometryR4/MuonDetectorDefs.h>
#include <GaudiKernel/SystemOfUnits.h>
#include <iostream>
#include <PathResolver/PathResolver.h>
#include <TFile.h>
#include <TTreeReader.h>

Go to the source code of this file.

Classes

struct  MdtChamber
 Helper struct to represent a full Mdt chamber. More...
struct  MdtChamber::TubePositioning

Macros

#define TEST_BASICPROP(attribute, propName)
#define TEST_TUBEPROP(attribute, propName)

Functions

std::ostream & operator<< (std::ostream &ostr, const MdtChamber &chamb)
 Translation of the station Index -> station Name.
std::set< MdtChamberreadTreeDump (const std::string &inputFile)
int main (int argc, char **argv)

Variables

constexpr double tolerance = 10 * Gaudi::Units::micrometer

Macro Definition Documentation

◆ TEST_BASICPROP

#define TEST_BASICPROP ( attribute,
propName )
Value:
if (std::abs(1.*test.attribute - 1.*reference.attribute) > tolerance) { \
std::cerr<<"runMdtGeoComparision() "<<__LINE__<<": "<<test \
<<" differs w.r.t "<<propName<<" "<< reference.attribute \
<<" (ref) vs. " <<test.attribute << " (test)" << std::endl; \
chamberOkay = false; \
}

Definition at line 106 of file runMdtGeoComparison.cxx.

106#define TEST_BASICPROP(attribute, propName) \
107 if (std::abs(1.*test.attribute - 1.*reference.attribute) > tolerance) { \
108 std::cerr<<"runMdtGeoComparision() "<<__LINE__<<": "<<test \
109 <<" differs w.r.t "<<propName<<" "<< reference.attribute \
110 <<" (ref) vs. " <<test.attribute << " (test)" << std::endl; \
111 chamberOkay = false; \
112 }

◆ TEST_TUBEPROP

#define TEST_TUBEPROP ( attribute,
propName )
Value:
if (std::abs(1.*refTube.attribute - 1.*testTube.attribute) > tolerance) { \
std::cerr<<"runMdtGeoComparision() "<<__LINE__<<": In "<<test<<" the tubes (" \
<<layer<<","<<std::setfill('0')<<std::setw(3)<<tube<<")" \
<<" differ w.r.t "<<propName<<". " \
<< refTube.attribute <<" (ref) vs. " <<testTube.attribute \
<< " (test)" << std::endl; \
chamberOkay = false; \
}

Definition at line 114 of file runMdtGeoComparison.cxx.

114#define TEST_TUBEPROP(attribute, propName) \
115 if (std::abs(1.*refTube.attribute - 1.*testTube.attribute) > tolerance) { \
116 std::cerr<<"runMdtGeoComparision() "<<__LINE__<<": In "<<test<<" the tubes (" \
117 <<layer<<","<<std::setfill('0')<<std::setw(3)<<tube<<")" \
118 <<" differ w.r.t "<<propName<<". " \
119 << refTube.attribute <<" (ref) vs. " <<testTube.attribute \
120 << " (test)" << std::endl; \
121 chamberOkay = false; \
122 }

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

check whether the files are xroot d -> otherwise call path resovler

Parse the tree dump

Start to loop over the chambers

We do not care whether the orientation of the coordinate system along the wire flips for negative chambers or not

The ultimate goal is to have the tube positioned at the same place. We maybe need the origin position later when we are adding the alignable transforms...

Check the tube transformations

Remember the tube staggering is in the (x-y) plane. Allow for deviations in the z-axis due to different cutouts

In cases where the tube coordinate systems are not aligned, there's no point in checking the position of the reaodout

Definition at line 245 of file runMdtGeoComparison.cxx.

245 {
246 std::string refFile{}, testFile{};
247
248 for (int arg = 1; arg < argc; ++arg) {
249 std::string the_arg{argv[arg]};
250 if (the_arg == "--refFile" && arg +1 < argc) {
251 refFile = std::string{argv[arg+1]};
252 ++arg;
253 } else if (the_arg == "--testFile" && arg + 1 < argc) {
254 testFile = std::string{argv[arg+1]};
255 ++arg;
256 }
257 }
258 if (refFile.empty()) {
259 std::cerr<<"Please parse the path of the reference file via --refFile "<<std::endl;
260 return EXIT_FAILURE;
261 }
262 if (testFile.empty()) {
263 std::cerr<<"Please parse the path of the test file via --testFile "<<std::endl;
264 return EXIT_FAILURE;
265 }
267 if (!refFile.starts_with( "root://")) refFile = PathResolver::FindCalibFile(refFile);
268 if (!testFile.starts_with( "root://")) testFile = PathResolver::FindCalibFile(testFile);
270 std::set<MdtChamber> refChambers = readTreeDump(refFile);
271 if (refChambers.empty()) {
272 std::cerr<<"The file "<<refFile<<" should contain at least one chamber "<<std::endl;
273 return EXIT_FAILURE;
274 }
275 std::set<MdtChamber> testChambers = readTreeDump(testFile);
276 if (testChambers.empty()) {
277 std::cerr<<"The file "<<testFile<<" should contain at least one chamber "<<std::endl;
278 return EXIT_FAILURE;
279 }
280 int return_code = EXIT_SUCCESS;
281 unsigned int goodChamb{0};
283 for (const MdtChamber& reference : refChambers) {
284 std::set<MdtChamber>::const_iterator test_itr = testChambers.find(reference);
285
286 if (test_itr == testChambers.end()) {
287 std::cerr<<"The chamber "<<reference<<" is not part of the testing "<<std::endl;
288 return_code = EXIT_FAILURE;
289 continue;
290 }
291 bool chamberOkay = true;
292 const MdtChamber& test = {*test_itr};
294 TEST_BASICPROP(numLayers, "number of layers");
295 TEST_BASICPROP(numTubes, "number of tubes");
296 TEST_BASICPROP(tubePitch, "tube pitch");
297 TEST_BASICPROP(tubeRadius, "tube radius");
298
299 const Amg::Transform3D distortion = test.geoModelTransform.inverse() * reference.geoModelTransform;
302 bool flippedChamb = {reference.id.eta < 0 && Amg::doesNotDeform(distortion * Amg::getRotateX3D(M_PI))};
303 if (!Amg::doesNotDeform(distortion) && !flippedChamb) {
304 std::cerr<<"runMdtGeoComparision() "<<__LINE__<<": The chamber coordinate systems rotate differently for "
305 <<reference<<". Difference in the coordinate transformation: "<<Amg::toString(distortion)
306 <<" --- refTrf: "<<Amg::toString(reference.geoModelTransform)
307 <<" --- testTrf: "<<Amg::toString(test.geoModelTransform)<<std::endl;
308 chamberOkay = false;
309 }
312 if (distortion.translation().mag() > tolerance) {
313 std::cout<<"The origins of the chamber coordinate systems are not exactly at the same point for "
314 <<reference<<". Translation shift: "<<Amg::toString(distortion.translation(), 2)<<std::endl;
315 }
317 bool stagFailure{false}, alignFailure{false}, readoutOrient{false};
318 for (unsigned int layer = 1; layer<= std::min(reference.numLayers, test.numLayers) ; ++layer) {
319 for (unsigned int tube = 1; tube <= std::min(reference.numTubes, test.numTubes); ++tube) {
320 using TubePositioning = MdtChamber::TubePositioning;
321 const TubePositioning& refTube = reference.getTube(layer, tube);
322 const TubePositioning& testTube = test.getTube(layer, tube);
323 const Amg::Transform3D tubeDistortion = testTube.localToGlobal.inverse() * refTube.localToGlobal;
324 bool flippedTube{reference.id.eta < 0 && Amg::doesNotDeform(tubeDistortion * Amg::getRotateX3D(M_PI))};
325
326 if (!alignFailure && !(Amg::doesNotDeform(tubeDistortion) || flippedTube)) {
327 std::cerr<<"runMdtGeoComparision() "<<__LINE__<<": In chamber "<<reference<<" the tube reference systems for ("<<layer<<", "
328 <<std::setfill('0')<<std::setw(3)<<tube<<") are not exactly aligned. "<<GeoTrf::toString(tubeDistortion)<<std::endl;
329 alignFailure = true;
330 }
333 if (!stagFailure && tubeDistortion.translation().perp() > tolerance) {
334 std::cerr<<"runMdtGeoComparision() "<<__LINE__<<": Misplaced staggering found in "<<reference<<" the tube ("<<layer
335 <<", "<<std::setfill('0')<<std::setw(3)<<tube<<") "
336 << Amg::toString(tubeDistortion.translation(), 3)<<", mag: "<<tubeDistortion.translation().mag()<<
337 ", perp: "<<tubeDistortion.translation().perp()<<std::endl;
338 if (tube > 1) stagFailure = true;
339 }
340
341 // TEST_TUBEPROP(tubeLength, "tube length");
342 // TEST_TUBEPROP(wireLength, "wire length");
343 TEST_TUBEPROP(activeLength, "active length");
346 if (alignFailure || readoutOrient) continue;
347 const Amg::Transform3D refSystem = refTube.localToGlobal.inverse();
348
349 const Amg::Vector3D refRO = refSystem * refTube.readoutPos;
350 const Amg::Vector3D testRO = refSystem* testTube.readoutPos;
351 if (refRO.z()* testRO.z() < 0.){
352 std::cerr<<"runMdtGeoComparision() "<<__LINE__<<": The readout is on different sites for chamber: "<<reference<<
353 ", layer "<<layer<<", tube: "<<std::setfill('0')<<std::setw(3)<<tube<<". "
354 <<Amg::toString(refRO, 2)<<" vs. "<<Amg::toString(testRO)<<std::endl;
355 readoutOrient = true;
356 }
357 }
358 if (stagFailure || alignFailure) {
359 chamberOkay = false;
360 }
361 }
362 if (!chamberOkay) {
363 return_code = EXIT_FAILURE;
364 continue;
365 }
366 const Amg::Transform3D alignableDistort = test.alignableTransform.inverse()*(reference.alignableTransform );
367 if (!Amg::doesNotDeform(alignableDistort) || alignableDistort.translation().mag() > tolerance) {
368 std::cerr<<"runMdtGeoComparision() "<<__LINE__<<": The alignable nodes are at differnt places for "
369 <<test<<". " <<GeoTrf::toString(alignableDistort, true)<<" chamber length: "<<
370 (reference.tubePitch * (1.*reference.numTubes + 0.5))<<std::endl;
371 chamberOkay = false;
372
373 } else {
374 std::cout<<"runMdtGeoComparision() "<<__LINE__<<": Found perfect agreement between new & old geometry for "<<reference<<std::endl;
375 ++goodChamb;
376 }
377 }
378 for (const MdtChamber& test : testChambers) {
379 if (!refChambers.count(test)) {
380 std::cerr<<"runMdtGeoComparision() "<<__LINE__<<": "<<test<<" is only in the test set."<<std::endl;
381 return_code = EXIT_FAILURE;
382 }
383 }
384 std::cout<<"runMdtGeoComparision() "<<__LINE__<<": "<<goodChamb<<"/"<<refChambers.size()<<" chambers are in perfect agreement. "<<std::endl;
385
386 return return_code;
387
388}
#define M_PI
static std::string FindCalibFile(const std::string &logical_file_name)
Amg::Transform3D getRotateX3D(double angle)
get a rotation transformation around X-axis
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
bool doesNotDeform(const Amg::Transform3D &trans)
Checks whether the linear part of the transformation rotates or stetches any of the basis vectors.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
@ layer
Definition HitInfo.h:79
#define TEST_TUBEPROP(attribute, propName)
#define TEST_BASICPROP(attribute, propName)
std::set< MdtChamber > readTreeDump(const std::string &inputFile)
Helper struct to represent a full Mdt chamber.

◆ operator<<()

std::ostream & operator<< ( std::ostream & ostr,
const MdtChamber & chamb )

Translation of the station Index -> station Name.

Dictionary taken from https://gitlab.cern.ch/atlas/athena/-/blob/main/DetectorDescription/IdDictParser/data/IdDictMuonSpectrometer_R.09.03.xml

Definition at line 90 of file runMdtGeoComparison.cxx.

90 {
91 static const std::map<int, std::string> stationDict{
92 {0, "BIL"}, {1, "BIS"}, {7, "BIR"},
93 {2, "BML"}, {3, "BMS"}, {8, "BMF"}, {53, "BME"}, {54, "BMG"}, {52, "BIM"},
94 {4, "BOL"}, {5, "BOS"}, {9, "BOF"}, {10, "BOG"},
95 {6, "BEE"}, {14, "EEL"}, {15, "EES"},
96 {13, "EIL"}, {49, "EIS"},
97 {17, "EML"}, {18, "EMS"},
98 {20, "EOL"}, {21, "EOS"}
99 };
100 ostr<<stationDict.at(chamb.id.stationIndex)<<" "<<chamb.id<<" "<<chamb.design;
101 return ostr;
102}
chamberIdentifier id

◆ readTreeDump()

std::set< MdtChamber > readTreeDump ( const std::string & inputFile)

Information to access each tube individually

Readout the information of each tube specifically

Definition at line 124 of file runMdtGeoComparison.cxx.

124 {
125 std::set<MdtChamber> to_ret{};
126 std::cout<<"Read the Mdt geometry tree dump from "<<inputFile<<std::endl;
127 std::unique_ptr<TFile> inFile{TFile::Open(inputFile.c_str())};
128 if (!inFile || !inFile->IsOpen()) {
129 std::cerr<<__FILE__<<":"<<__LINE__<<" Failed to open "<<inputFile<<std::endl;
130 return to_ret;
131 }
132 TTreeReader treeReader("MdtGeoModelTree", inFile.get());
133 if (treeReader.IsInvalid()){
134 std::cerr<<__FILE__<<":"<<__LINE__<<" The file "<<inputFile<<" does not contain the 'MdtGeoModelTree'"<<std::endl;
135 return to_ret;
136 }
137
138 TTreeReaderValue<unsigned short> stationIndex{treeReader, "stationIndex"};
139 TTreeReaderValue<short> stationEta{treeReader, "stationEta"};
140 TTreeReaderValue<short> stationPhi{treeReader, "stationPhi"};
141 TTreeReaderValue<short> stationML{treeReader, "stationMultiLayer"};
142 TTreeReaderValue<std::string> chamberDesign{treeReader,"chamberDesign"};
143
144 TTreeReaderValue<double> tubeRadius{treeReader, "tubeRadius"};
145 TTreeReaderValue<double> tubePitch{treeReader, "tubePitch"};
146 TTreeReaderValue<unsigned short> numTubes{treeReader, "numTubes"};
147 TTreeReaderValue<unsigned short> numLayers{treeReader, "numLayers"};
148
149 TTreeReaderValue<std::vector<float>> geoModelTransformX{treeReader, "GeoModelTransformX"};
150 TTreeReaderValue<std::vector<float>> geoModelTransformY{treeReader, "GeoModelTransformY"};
151 TTreeReaderValue<std::vector<float>> geoModelTransformZ{treeReader, "GeoModelTransformZ"};
152
153 TTreeReaderValue<std::vector<float>> alignableNodeX{treeReader, "AlignableNodeX"};
154 TTreeReaderValue<std::vector<float>> alignableNodeY{treeReader, "AlignableNodeY"};
155 TTreeReaderValue<std::vector<float>> alignableNodeZ{treeReader, "AlignableNodeZ"};
156
157
159 TTreeReaderValue<std::vector<unsigned short>> tubeLayer{treeReader, "tubeLayer"};
160 TTreeReaderValue<std::vector<unsigned short>> tubeNumber{treeReader, "tubeNumber"};
161
162 TTreeReaderValue<std::vector<double>> tubeLength{treeReader, "tubeLength"};
163 TTreeReaderValue<std::vector<double>> activeTubeLength{treeReader, "activeTubeLength"};
164 TTreeReaderValue<std::vector<double>> wireLength{treeReader, "wireLength"};
165
166 TTreeReaderValue<std::vector<float>> tubeTransformTransX{treeReader, "tubeTransformTranslationX"};
167 TTreeReaderValue<std::vector<float>> tubeTransformTransY{treeReader, "tubeTransformTranslationY"};
168 TTreeReaderValue<std::vector<float>> tubeTransformTransZ{treeReader, "tubeTransformTranslationZ"};
169
170 TTreeReaderValue<std::vector<float>> tubeTransformCol0X{treeReader, "tubeTransformLinearCol1X"};
171 TTreeReaderValue<std::vector<float>> tubeTransformCol0Y{treeReader, "tubeTransformLinearCol1Y"};
172 TTreeReaderValue<std::vector<float>> tubeTransformCol0Z{treeReader, "tubeTransformLinearCol1Z"};
173
174 TTreeReaderValue<std::vector<float>> tubeTransformCol1X{treeReader, "tubeTransformLinearCol2X"};
175 TTreeReaderValue<std::vector<float>> tubeTransformCol1Y{treeReader, "tubeTransformLinearCol2Y"};
176 TTreeReaderValue<std::vector<float>> tubeTransformCol1Z{treeReader, "tubeTransformLinearCol2Z"};
177
178 TTreeReaderValue<std::vector<float>> tubeTransformCol2X{treeReader, "tubeTransformLinearCol3X"};
179 TTreeReaderValue<std::vector<float>> tubeTransformCol2Y{treeReader, "tubeTransformLinearCol3Y"};
180 TTreeReaderValue<std::vector<float>> tubeTransformCol2Z{treeReader, "tubeTransformLinearCol3Z"};
181
182 TTreeReaderValue<std::vector<float>> readOutPosX{treeReader, "readOutPosX"};
183 TTreeReaderValue<std::vector<float>> readOutPosY{treeReader, "readOutPosY"};
184 TTreeReaderValue<std::vector<float>> readOutPosZ{treeReader, "readOutPosZ"};
185
186 while (treeReader.Next()) {
187 MdtChamber newchamber{};
188
189 newchamber.id.stationIndex = (*stationIndex);
190 newchamber.id.eta = (*stationEta);
191 newchamber.id.phi = (*stationPhi);
192 newchamber.id.multilayer = (*stationML);
193 newchamber.design = (*chamberDesign);
194
195 newchamber.tubeRadius = (*tubeRadius);
196 newchamber.tubePitch = (*tubePitch);
197
198 newchamber.numTubes = (*numTubes);
199 newchamber.numLayers = (*numLayers);
200
201 Amg::RotationMatrix3D geoRot{Amg::RotationMatrix3D::Identity()};
202 geoRot.col(0) = Amg::Vector3D((*geoModelTransformX)[1], (*geoModelTransformY)[1], (*geoModelTransformZ)[1]);
203 geoRot.col(1) = Amg::Vector3D((*geoModelTransformX)[2], (*geoModelTransformY)[2], (*geoModelTransformZ)[2]);
204 geoRot.col(2) = Amg::Vector3D((*geoModelTransformX)[3], (*geoModelTransformY)[3], (*geoModelTransformZ)[3]);
205 Amg::Vector3D geoTrans{(*geoModelTransformX)[0], (*geoModelTransformY)[0], (*geoModelTransformZ)[0]};
206 newchamber.geoModelTransform = Amg::getTransformFromRotTransl(std::move(geoRot), std::move(geoTrans));
207
208 geoRot.col(0) = Amg::Vector3D((*alignableNodeX)[1], (*alignableNodeY)[1], (*alignableNodeZ)[1]);
209 geoRot.col(1) = Amg::Vector3D((*alignableNodeX)[2], (*alignableNodeY)[2], (*alignableNodeZ)[2]);
210 geoRot.col(2) = Amg::Vector3D((*alignableNodeX)[3], (*alignableNodeY)[3], (*alignableNodeZ)[3]);
211 geoTrans = Amg::Vector3D{(*alignableNodeX)[0], (*alignableNodeY)[0], (*alignableNodeZ)[0]};
212 newchamber.alignableTransform = Amg::getTransformFromRotTransl(std::move(geoRot), std::move(geoTrans));
213
214
216 for (size_t t = 0; t < tubeLayer->size(); ++t){
217 using TubePositioning = MdtChamber::TubePositioning;
218 TubePositioning newTube{};
219 newTube.layerNum = (*tubeLayer)[t];
220 newTube.tubeNum = (*tubeNumber)[t];
221 newTube.tubeLength = (*tubeLength)[t];
222 newTube.wireLength = (*wireLength)[t];
223 Amg::RotationMatrix3D tubeRot{Amg::RotationMatrix3D::Identity()};
224 tubeRot.col(0) = Amg::Vector3D((*tubeTransformCol0X)[t],(*tubeTransformCol0Y)[t], (*tubeTransformCol0Z)[t]);
225 tubeRot.col(1) = Amg::Vector3D((*tubeTransformCol1X)[t],(*tubeTransformCol1Y)[t], (*tubeTransformCol1Z)[t]);
226 tubeRot.col(2) = Amg::Vector3D((*tubeTransformCol2X)[t],(*tubeTransformCol2Y)[t], (*tubeTransformCol2Z)[t]);
227 Amg::Vector3D tubeTrans{(*tubeTransformTransX)[t],(*tubeTransformTransY)[t], (*tubeTransformTransZ)[t]};
228 newTube.localToGlobal = Amg::getTransformFromRotTransl(std::move(tubeRot), std::move(tubeTrans));
229 newTube.readoutPos = Amg::Vector3D{(*readOutPosX)[t],(*readOutPosY)[t],(*readOutPosZ)[t]};
230 newchamber.insertTube(std::move(newTube));
231 }
232
233 auto insert_itr = to_ret.insert(std::move(newchamber));
234 if (!insert_itr.second) {
235 std::stringstream err{};
236 err<<__FILE__<<":"<<__LINE__<<" The chamber "<<(*insert_itr.first).id
237 <<" has already been inserted. "<<std::endl;
238 throw std::runtime_error(err.str());
239 }
240 }
241 std::cout<<"File parsing is finished. Found in total "<<to_ret.size()<<" readout element dumps "<<std::endl;
242 return to_ret;
243}
double tubeLength
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
Amg::Transform3D getTransformFromRotTransl(Amg::RotationMatrix3D rot, Amg::Vector3D transl_vec)
constexpr unsigned int numLayers()
Definition HIEventDefs.h:23
constexpr uint8_t stationPhi
station Phi 1 to 8
str inFile
Definition makeTOC.py:5
int8_t & multilayer
Phi sector of the MDT station.
int8_t & eta
Station of the chamber (i.e, BIL,BIS,etc.)
int8_t & phi
Eta of the MDT station.
unsigned int layerNum
Layer to which the tube belongs.
Amg::Transform3D geoModelTransform
Transformation of the underlying GeoModel element.
void insertTube(TubePositioning &&newTube)
double tubePitch
Pitch between two tubes.
unsigned int numLayers
Number of tube layers.
unsigned int numTubes
Number of tubes.
Amg::Transform3D alignableTransform
Transformation of the underlying Alignable node.
double tubeRadius
Inner tube radius.

Variable Documentation

◆ tolerance

double tolerance = 10 * Gaudi::Units::micrometer
constexpr

Definition at line 104 of file runMdtGeoComparison.cxx.