File indexing completed on 2024-09-07 04:37:11
0001
0002
0003
0004
0005
0006 #include "DD4hep_MagGeoBuilder.h"
0007 #include "bLayer.h"
0008 #include "eSector.h"
0009 #include "InterpolatorBuilder.h"
0010
0011 #include "MagneticField/Layers/interface/MagBLayer.h"
0012 #include "MagneticField/Layers/interface/MagESector.h"
0013
0014 #include "DetectorDescription/DDCMS/interface/DDFilteredView.h"
0015
0016 #include "Utilities/BinningTools/interface/ClusterizingHistogram.h"
0017
0018 #include "MagneticField/Interpolation/interface/MagProviderInterpol.h"
0019 #include "MagneticField/Interpolation/interface/MFGrid.h"
0020
0021 #include "MagneticField/VolumeGeometry/interface/MagVolume6Faces.h"
0022 #include "MagneticField/VolumeGeometry/interface/MagExceptions.h"
0023
0024 #include "DataFormats/Math/interface/deltaPhi.h"
0025
0026 #include "FWCore/Utilities/interface/Exception.h"
0027 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0028 #include "Utilities/General/interface/precomputed_value_sort.h"
0029
0030 #include <iomanip>
0031 #include <string>
0032 #include <vector>
0033 #include <sstream>
0034 #include <algorithm>
0035 #include <iterator>
0036 #include <map>
0037 #include <set>
0038 #include <boost/algorithm/string/replace.hpp>
0039
0040 using namespace std;
0041 using namespace magneticfield;
0042 using namespace edm;
0043 using namespace angle_units::operators;
0044
0045 MagGeoBuilder::MagGeoBuilder(string tableSet, int geometryVersion, bool debug, bool mergeFile)
0046 : tableSet_(tableSet),
0047 geometryVersion_(geometryVersion),
0048 theGridFiles_(nullptr),
0049 debug_(debug),
0050 useMergeFileIfAvailable_(mergeFile) {
0051 LogTrace("MagGeoBuilder") << "Constructing a MagGeoBuilder";
0052 }
0053
0054 MagGeoBuilder::~MagGeoBuilder() {
0055 for (auto i : bVolumes_) {
0056 delete i;
0057 }
0058 for (auto i : eVolumes_) {
0059 delete i;
0060 }
0061 }
0062
0063 void MagGeoBuilder::summary(handles& volumes) const {
0064
0065 int ivolumes = volumes.size();
0066 int isurfaces = ivolumes * 6;
0067 int iassigned = 0;
0068 int iunique = 0;
0069 int iref_ass = 0;
0070 int iref_nass = 0;
0071
0072 set<const void*> ptrs;
0073
0074 for (auto i : volumes) {
0075 DDSolidShape theShape = i->shape();
0076 if (theShape == DDSolidShape::ddbox || theShape == DDSolidShape::ddcons || theShape == DDSolidShape::ddtrap ||
0077 theShape == DDSolidShape::ddtubs) {
0078 for (int side = 0; side < 6; ++side) {
0079 int references = i->references(side);
0080 if (i->isPlaneMatched(side)) {
0081 ++iassigned;
0082 bool firstOcc = (ptrs.insert(&(i->surface(side)))).second;
0083 if (firstOcc)
0084 iref_ass += references;
0085 if (references < 2) {
0086 LogTrace("MagGeoBuilder") << "*** Only 1 ref, vol: " << i->volumeno << " # " << i->copyno
0087 << " side: " << side;
0088 }
0089 } else {
0090 iref_nass += references;
0091 if (references > 1) {
0092 LogTrace("MagGeoBuilder") << "*** Ref_nass >1 ";
0093 }
0094 }
0095 }
0096 }
0097 }
0098 iunique = ptrs.size();
0099
0100 LogTrace("MagGeoBuilder") << " volumes " << ivolumes << newln << " surfaces " << isurfaces << newln
0101 << " assigned " << iassigned << newln << " unique " << iunique << newln
0102 << " iref_ass " << iref_ass << newln << " iref_nass " << iref_nass;
0103 }
0104
0105 void MagGeoBuilder::build(const cms::DDDetector* det) {
0106 cms::Volume top = det->worldVolume();
0107 cms::DDFilteredView fv(det, top);
0108 if (fv.next(0) == false) {
0109 LogError("MagGeoBuilder") << "Filtered view is empty. Cannot build.";
0110 return;
0111 }
0112
0113
0114 map<string, MagProviderInterpol*> bInterpolators;
0115 map<string, MagProviderInterpol*> eInterpolators;
0116
0117
0118 int bVolCount = 0;
0119 int eVolCount = 0;
0120
0121 const string magfStr{"MAGF"};
0122 const string magfStr2{"cmsMagneticField:MAGF"};
0123 if (fv.name() != magfStr && fv.name() != magfStr2) {
0124 std::string topNodeName(fv.name());
0125 LogTrace("MagGeoBuilder") << "Filtered view top node name is " << topNodeName << ".";
0126
0127
0128 bool doSubDets = fv.next(0);
0129
0130 bool go = true;
0131 while (go && doSubDets) {
0132 LogTrace("MagGeoBuilder") << "Next node name is " << fv.name() << ".";
0133 if (fv.name() == magfStr)
0134 break;
0135 else
0136 go = fv.next(0);
0137 }
0138 if (!go) {
0139 throw cms::Exception("NoMAGF")
0140 << " Neither the top node, nor any child node of the filtered view is \"MAGF\" but the top node is instead \""
0141 << topNodeName << "\"";
0142 }
0143 }
0144
0145
0146 bool doSubDets = fv.next(0);
0147 if (doSubDets == false) {
0148 LogError("MagGeoBuilder") << "Filtered view has no node. Cannot build.";
0149 return;
0150 }
0151 InterpolatorBuilder interpolatorBuilder(tableSet_, useMergeFileIfAvailable_);
0152 while (doSubDets) {
0153 string name = fv.volume().volume().name();
0154 LogTrace("MagGeoBuilder") << "Name: " << name;
0155
0156 bool expand = false;
0157 volumeHandle* v = new volumeHandle(fv, expand, debug_);
0158
0159 if (theGridFiles_ != nullptr) {
0160 int key = (v->volumeno) * 100 + v->copyno;
0161 TableFileMap::const_iterator itable = theGridFiles_->find(key);
0162 if (itable == theGridFiles_->end()) {
0163 key = (v->volumeno) * 100;
0164 itable = theGridFiles_->find(key);
0165 }
0166
0167 if (itable != theGridFiles_->end()) {
0168 string magFile = (*itable).second.first;
0169 stringstream conv;
0170 string svol, ssec;
0171 conv << setfill('0') << setw(3) << v->volumeno << " " << setw(2)
0172 << v->copyno;
0173 conv >> svol >> ssec;
0174 boost::replace_all(magFile, "[v]", svol);
0175 boost::replace_all(magFile, "[s]", ssec);
0176 int masterSector = (*itable).second.second;
0177 if (masterSector == 0)
0178 masterSector = v->copyno;
0179 v->magFile = magFile;
0180 v->masterSector = masterSector;
0181 } else {
0182 edm::LogError("MagGeoBuilderbuild") << "ERROR: no table spec found for V " << v->volumeno << ":" << v->copyno;
0183 }
0184 }
0185
0186
0187 float Z = v->center().z();
0188 float R = v->center().perp();
0189 LogTrace("MagGeoBuilder") << " Vol R and Z values determine barrel or endcap. R = " << R << ", Z = " << Z;
0190
0191
0192
0193
0194
0195
0196
0197 if ((fabs(Z) < 647. || (R > 350. && fabs(Z) < 662.)) &&
0198 !(fabs(Z) > 480 && R < 172)
0199
0200
0201
0202 ) {
0203 LogTrace("MagGeoBuilder") << " (Barrel)";
0204 bVolumes_.push_back(v);
0205
0206
0207
0208
0209 if (v->copyno == v->masterSector) {
0210 auto i = buildInterpolator(v, interpolatorBuilder);
0211 if (i) {
0212 bInterpolators[v->magFile] = i;
0213 }
0214 ++bVolCount;
0215 }
0216 } else {
0217 LogTrace("MagGeoBuilder") << " (Endcaps)";
0218 eVolumes_.push_back(v);
0219 if (v->copyno == v->masterSector) {
0220 auto i = buildInterpolator(v, interpolatorBuilder);
0221 if (i) {
0222 eInterpolators[v->magFile] = i;
0223 }
0224 ++eVolCount;
0225 }
0226 }
0227 doSubDets = fv.next(0);
0228 }
0229
0230 LogTrace("MagGeoBuilder") << "Number of volumes (barrel): " << bVolumes_.size() << newln
0231 << "Number of volumes (endcap): " << eVolumes_.size();
0232 LogTrace("MagGeoBuilder") << "**********************************************************";
0233
0234
0235
0236
0237
0238
0239
0240 if (debug_) {
0241 LogTrace("MagGeoBuilder") << "-----------------------";
0242 LogTrace("MagGeoBuilder") << "SUMMARY: Barrel ";
0243 summary(bVolumes_);
0244
0245 LogTrace("MagGeoBuilder") << "SUMMARY: Endcaps ";
0246 summary(eVolumes_);
0247 LogTrace("MagGeoBuilder") << "-----------------------";
0248 }
0249
0250
0251
0252
0253 if (bVolumes_.empty()) {
0254 LogError("MagGeoBuilder") << "Error: Barrel volumes are missing. Terminating build.";
0255 return;
0256 }
0257 vector<bLayer> layers;
0258 precomputed_value_sort(bVolumes_.begin(), bVolumes_.end(), ExtractRN());
0259
0260
0261 const float resolution = 1.;
0262 float rmin = bVolumes_.front()->RN() - resolution;
0263 float rmax = bVolumes_.back()->RN() + resolution;
0264 ClusterizingHistogram hisR(int((rmax - rmin) / resolution) + 1, rmin, rmax);
0265
0266 LogTrace("MagGeoBuilder") << " R layers: " << rmin << " " << rmax;
0267
0268 handles::const_iterator first = bVolumes_.begin();
0269 handles::const_iterator last = bVolumes_.end();
0270
0271 for (auto i : bVolumes_) {
0272 hisR.fill(i->RN());
0273 }
0274 vector<float> rClust = hisR.clusterize(resolution);
0275
0276 handles::const_iterator ringStart = first;
0277 handles::const_iterator separ = first;
0278
0279 for (unsigned int i = 0; i < rClust.size() - 1; ++i) {
0280 if (debug_)
0281 LogTrace("MagGeoBuilder") << " Layer at RN = " << rClust[i];
0282 float rSepar = (rClust[i] + rClust[i + 1]) / 2.f;
0283 while ((*separ)->RN() < rSepar)
0284 ++separ;
0285
0286 bLayer thislayer(ringStart, separ, debug_);
0287 layers.push_back(thislayer);
0288 ringStart = separ;
0289 }
0290 {
0291 if (debug_)
0292 LogTrace("MagGeoBuilder") << " Layer at RN = " << rClust.back();
0293 bLayer thislayer(separ, last, debug_);
0294 layers.push_back(thislayer);
0295 }
0296
0297 LogTrace("MagGeoBuilder") << "Barrel: Found " << rClust.size() << " clusters in R, " << layers.size() << " layers ";
0298
0299
0300
0301 vector<eSector> sectors;
0302
0303
0304 constexpr float phireso = 0.05;
0305 constexpr int twoPiOverPhiReso = static_cast<int>(2._pi / phireso) + 1;
0306 ClusterizingHistogram hisPhi(twoPiOverPhiReso, -1._pi, 1._pi);
0307
0308 for (auto i : eVolumes_) {
0309 hisPhi.fill(i->minPhi());
0310 }
0311 vector<float> phiClust = hisPhi.clusterize(phireso);
0312 int nESectors = phiClust.size();
0313 if (nESectors <= 0) {
0314 LogError("MagGeoBuilder") << "ERROR: Endcap sectors are missing. Terminating build.";
0315 return;
0316 }
0317 if (debug_ && (nESectors % 12) != 0) {
0318 LogTrace("MagGeoBuilder") << "ERROR: unexpected # of endcap sectors: " << nESectors;
0319 }
0320
0321
0322 precomputed_value_sort(eVolumes_.begin(), eVolumes_.end(), ExtractPhi());
0323
0324
0325
0326 float lastBinPhi = phiClust.back();
0327 handles::reverse_iterator ri = eVolumes_.rbegin();
0328 while ((*ri)->center().phi() > lastBinPhi) {
0329 ++ri;
0330 }
0331 if (ri != eVolumes_.rbegin()) {
0332
0333
0334 handles::iterator newbeg = ri.base();
0335 rotate(eVolumes_.begin(), newbeg, eVolumes_.end());
0336 }
0337
0338
0339 int offset = eVolumes_.size() / nESectors;
0340 for (int i = 0; i < nESectors; ++i) {
0341 if (debug_) {
0342 LogTrace("MagGeoBuilder") << " Sector at phi = " << (*(eVolumes_.begin() + ((i)*offset)))->center().phi();
0343
0344 int secCopyNo = -1;
0345 for (handles::const_iterator iv = eVolumes_.begin() + ((i)*offset); iv != eVolumes_.begin() + ((i + 1) * offset);
0346 ++iv) {
0347 if (secCopyNo >= 0 && (*iv)->copyno != secCopyNo)
0348 LogTrace("MagGeoBuilder") << "ERROR: volume copyno " << (*iv)->name << ":" << (*iv)->copyno
0349 << " differs from others in same sectors with copyno = " << secCopyNo;
0350 secCopyNo = (*iv)->copyno;
0351 }
0352 }
0353
0354 sectors.push_back(eSector(eVolumes_.begin() + ((i)*offset), eVolumes_.begin() + ((i + 1) * offset), debug_));
0355 }
0356
0357 LogTrace("MagGeoBuilder") << "Endcap: Found " << sectors.size() << " sectors ";
0358
0359
0360
0361
0362
0363
0364
0365 buildMagVolumes(bVolumes_, bInterpolators);
0366
0367
0368 for (const auto& ilay : layers) {
0369 mBLayers_.push_back(ilay.buildMagBLayer());
0370 }
0371 LogTrace("MagGeoBuilder") << "*** BARREL ********************************************" << newln
0372 << "Number of different volumes = " << bVolCount << newln
0373 << "Number of interpolators built = " << bInterpolators.size() << newln
0374 << "Number of MagBLayers built = " << mBLayers_.size();
0375 if (debug_) {
0376 testInside(bVolumes_);
0377 }
0378
0379
0380 buildMagVolumes(eVolumes_, eInterpolators);
0381
0382
0383 for (const auto& isec : sectors) {
0384 mESectors_.push_back(isec.buildMagESector());
0385 }
0386 LogTrace("MagGeoBuilder") << "*** ENDCAP ********************************************" << newln
0387 << "Number of different volumes = " << eVolCount << newln
0388 << "Number of interpolators built = " << eInterpolators.size() << newln
0389 << "Number of MagESector built = " << mESectors_.size();
0390 if (debug_) {
0391 testInside(eVolumes_);
0392 }
0393 }
0394
0395 void MagGeoBuilder::buildMagVolumes(const handles& volumes,
0396 const map<string, MagProviderInterpol*>& interpolators) const {
0397
0398 for (auto vol : volumes) {
0399 const MagProviderInterpol* mp = nullptr;
0400 auto found = interpolators.find(vol->magFile);
0401 if (found != interpolators.end()) {
0402 mp = found->second;
0403 } else {
0404 edm::LogError("MagGeoBuilder") << "No interpolator found for file " << vol->magFile << " vol: " << vol->volumeno
0405 << "\n"
0406 << interpolators.size();
0407 }
0408
0409
0410
0411 int key = (vol->volumeno) * 100 + vol->copyno;
0412 map<int, double>::const_iterator isf = theScalingFactors_.find(key);
0413 if (isf == theScalingFactors_.end()) {
0414 key = (vol->volumeno) * 100;
0415 isf = theScalingFactors_.find(key);
0416 }
0417
0418 double sf = 1.;
0419 if (isf != theScalingFactors_.end()) {
0420 sf = (*isf).second;
0421
0422 LogTrace("MagGeoBuilder") << "Applying scaling factor " << sf << " to " << vol->volumeno << "[" << vol->copyno
0423 << "] (key:" << key << ")";
0424 }
0425
0426 const GloballyPositioned<float>* gpos = vol->placement();
0427 vol->magVolume = new MagVolume6Faces(gpos->position(), gpos->rotation(), vol->sides(), mp, sf);
0428
0429 if (vol->copyno == vol->masterSector) {
0430 vol->magVolume->ownsFieldProvider(true);
0431 }
0432
0433 vol->magVolume->setIsIron(vol->isIron());
0434
0435
0436 vol->magVolume->volumeNo = vol->volumeno;
0437 vol->magVolume->copyno = vol->copyno;
0438 }
0439 }
0440
0441 MagProviderInterpol* MagGeoBuilder::buildInterpolator(const volumeHandle* vol, InterpolatorBuilder& builder) const {
0442 MagProviderInterpol* retValue = nullptr;
0443 LogTrace("MagGeoBuilder") << "Building interpolator from " << vol->volumeno << " copyno " << vol->copyno << " at "
0444 << vol->center() << " phi: " << static_cast<double>(vol->center().phi()) / 1._pi
0445 << " pi, file: " << vol->magFile << " master: " << vol->masterSector;
0446 if (debug_) {
0447
0448 double masterSectorPhi = (vol->masterSector - 1) * 1._pi / 6.;
0449 double delta = std::abs(vol->center().phi() - masterSectorPhi);
0450 if (delta > (1._pi / 9.)) {
0451 LogTrace("MagGeoBuilder") << "***WARNING wrong sector? Vol delta from master sector is " << delta / 1._pi
0452 << " pi";
0453 }
0454 }
0455
0456 try {
0457 retValue = builder.build(vol).release();
0458 } catch (edm::Exception& exc) {
0459 cerr << "MagGeoBuilder: exception in reading table; " << exc.what() << endl;
0460 if (!debug_)
0461 throw;
0462 return nullptr;
0463 } catch (MagException const& exc) {
0464 LogTrace("MagGeoBuilder") << exc.what();
0465 if (!debug_)
0466 throw;
0467 return nullptr;
0468 }
0469
0470 if (debug_) {
0471
0472 const MagVolume6Faces tempVolume(
0473 vol->placement()->position(), vol->placement()->rotation(), vol->sides(), retValue);
0474
0475 const MFGrid* grid = dynamic_cast<const MFGrid*>(retValue);
0476 if (grid != nullptr) {
0477 Dimensions sizes = grid->dimensions();
0478 LogTrace("MagGeoBuilder") << "Grid has 3 dimensions "
0479 << " number of nodes is " << sizes.w << " " << sizes.h << " " << sizes.d;
0480
0481 const double tolerance = 0.03;
0482
0483 size_t dumpCount = 0;
0484 for (int j = 0; j < sizes.h; j++) {
0485 for (int k = 0; k < sizes.d; k++) {
0486 for (int i = 0; i < sizes.w; i++) {
0487 MFGrid::LocalPoint lp = grid->nodePosition(i, j, k);
0488 if (!tempVolume.inside(lp, tolerance)) {
0489 if (++dumpCount < 2) {
0490 MFGrid::GlobalPoint gp = tempVolume.toGlobal(lp);
0491 LogTrace("MagGeoBuilder") << "GRID ERROR: " << i << " " << j << " " << k << " local: " << lp
0492 << " global: " << gp << " R= " << gp.perp() << " phi=" << gp.phi();
0493 }
0494 }
0495 }
0496 }
0497 }
0498
0499 LogTrace("MagGeoBuilder") << "Volume:" << vol->volumeno
0500 << " : Number of grid points outside the MagVolume: " << dumpCount << "/"
0501 << sizes.w * sizes.h * sizes.d;
0502 }
0503 }
0504 return retValue;
0505 }
0506
0507 void MagGeoBuilder::testInside(handles& volumes) const {
0508
0509 LogTrace("MagGeoBuilder") << "--------------------------------------------------";
0510 LogTrace("MagGeoBuilder") << " inside(center) test";
0511 for (auto vol : volumes) {
0512 for (auto i : volumes) {
0513 if (i == vol)
0514 continue;
0515
0516 if (i->magVolume->inside(vol->center())) {
0517 LogTrace("MagGeoBuilder") << "*** ERROR: center of V " << vol->volumeno << ":" << vol->copyno << " is inside V "
0518 << i->volumeno << ":" << i->copyno;
0519 }
0520 }
0521
0522 if (vol->magVolume->inside(vol->center())) {
0523 LogTrace("MagGeoBuilder") << "V " << vol->volumeno << ":" << vol->copyno << " OK ";
0524 } else {
0525 LogTrace("MagGeoBuilder") << "*** ERROR: center of volume is not inside it, " << vol->volumeno << ":"
0526 << vol->copyno;
0527 }
0528 }
0529 LogTrace("MagGeoBuilder") << "--------------------------------------------------";
0530 }
0531
0532 vector<MagBLayer*> MagGeoBuilder::barrelLayers() const { return mBLayers_; }
0533
0534 vector<MagESector*> MagGeoBuilder::endcapSectors() const { return mESectors_; }
0535
0536 vector<MagVolume6Faces*> MagGeoBuilder::barrelVolumes() const {
0537 vector<MagVolume6Faces*> v;
0538 v.reserve(bVolumes_.size());
0539 for (auto i : bVolumes_) {
0540 v.push_back(i->magVolume);
0541 }
0542 return v;
0543 }
0544
0545 vector<MagVolume6Faces*> MagGeoBuilder::endcapVolumes() const {
0546 vector<MagVolume6Faces*> v;
0547 v.reserve(eVolumes_.size());
0548 for (auto i : eVolumes_) {
0549 v.push_back(i->magVolume);
0550 }
0551 return v;
0552 }
0553
0554 float MagGeoBuilder::maxR() const {
0555
0556 return 900.;
0557 }
0558
0559 float MagGeoBuilder::maxZ() const {
0560
0561 if (geometryVersion_ >= 160812)
0562 return 2400.;
0563 else if (geometryVersion_ >= 120812)
0564 return 2000.;
0565 else
0566 return 1600.;
0567 }
0568
0569 void MagGeoBuilder::setScaling(const std::vector<int>& keys, const std::vector<double>& values) {
0570 if (keys.size() != values.size()) {
0571 throw cms::Exception("InvalidParameter")
0572 << "Invalid field scaling parameters 'scalingVolumes' and 'scalingFactors' ";
0573 }
0574 for (unsigned int i = 0; i < keys.size(); ++i) {
0575 theScalingFactors_[keys[i]] = values[i];
0576 }
0577 }
0578
0579 void MagGeoBuilder::setGridFiles(const TableFileMap& gridFiles) { theGridFiles_ = &gridFiles; }