00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "MagneticField/GeomBuilder/src/MagGeoBuilderFromDDD.h"
00010 #include "MagneticField/GeomBuilder/src/volumeHandle.h"
00011 #include "MagneticField/GeomBuilder/src/bSlab.h"
00012 #include "MagneticField/GeomBuilder/src/bRod.h"
00013 #include "MagneticField/GeomBuilder/src/bSector.h"
00014 #include "MagneticField/GeomBuilder/src/bLayer.h"
00015 #include "MagneticField/GeomBuilder/src/eSector.h"
00016 #include "MagneticField/GeomBuilder/src/eLayer.h"
00017 #include "MagneticField/GeomBuilder/src/FakeInterpolator.h"
00018
00019 #include "MagneticField/Layers/interface/MagBLayer.h"
00020 #include "MagneticField/Layers/interface/MagESector.h"
00021
00022 #include "FWCore/ParameterSet/interface/FileInPath.h"
00023
00024 #include "DetectorDescription/Core/interface/DDCompactView.h"
00025 #include "DetectorDescription/Core/interface/DDFilteredView.h"
00026 #include "DetectorDescription/Core/interface/DDFilter.h"
00027
00028 #include "Utilities/BinningTools/interface/ClusterizingHistogram.h"
00029 #include "CLHEP/Units/GlobalSystemOfUnits.h"
00030
00031 #include "MagneticField/Interpolation/interface/MagProviderInterpol.h"
00032 #include "MagneticField/Interpolation/interface/MFGridFactory.h"
00033 #include "MagneticField/Interpolation/interface/MFGrid.h"
00034
00035 #include "MagneticField/VolumeGeometry/interface/MagVolume6Faces.h"
00036 #include "MagneticField/VolumeGeometry/interface/MagExceptions.h"
00037 #include "MagneticField/Layers/interface/MagVerbosity.h"
00038
00039 #include "DataFormats/GeometryVector/interface/Pi.h"
00040
00041 #include "FWCore/Utilities/interface/Exception.h"
00042 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00043
00044 #include <string>
00045 #include <vector>
00046 #include <iostream>
00047 #include <sstream>
00048 #include <algorithm>
00049 #include <iterator>
00050 #include <map>
00051 #include <set>
00052 #include <iomanip>
00053 #include <boost/algorithm/string/replace.hpp>
00054 #include "Utilities/General/interface/precomputed_value_sort.h"
00055
00056
00057 bool MagGeoBuilderFromDDD::debug;
00058
00059 using namespace std;
00060 using namespace magneticfield;
00061
00062
00063 MagGeoBuilderFromDDD::MagGeoBuilderFromDDD(string tableSet_,int geometryVersion_, bool debug_) :
00064 tableSet (tableSet_),
00065 geometryVersion(geometryVersion_),
00066 theGridFiles(0)
00067 {
00068 debug = debug_;
00069 if (debug) cout << "Constructing a MagGeoBuilderFromDDD" <<endl;
00070 }
00071
00072 MagGeoBuilderFromDDD::~MagGeoBuilderFromDDD(){
00073 for (handles::const_iterator i=bVolumes.begin();
00074 i!=bVolumes.end(); ++i){
00075 delete (*i);
00076 }
00077
00078 for (handles::const_iterator i=eVolumes.begin();
00079 i!=eVolumes.end(); ++i){
00080 delete (*i);
00081 }
00082 }
00083
00084
00085 void MagGeoBuilderFromDDD::summary(handles & volumes){
00086
00087 int ivolumes = volumes.size();
00088 int isurfaces = ivolumes*6;
00089 int iassigned = 0;
00090 int iunique = 0;
00091 int iref_ass = 0;
00092 int iref_nass = 0;
00093
00094 set<const void *> ptrs;
00095
00096 handles::const_iterator first = volumes.begin();
00097 handles::const_iterator last = volumes.end();
00098
00099 for (handles::const_iterator i=first; i!=last; ++i){
00100 if (int((*i)->shape())>4) continue;
00101 for (int side = 0; side < 6; ++side) {
00102 int references = (*i)->references(side);
00103 if ((*i)->isPlaneMatched(side)) {
00104 ++iassigned;
00105 bool firstOcc = (ptrs.insert(&((*i)->surface(side)))).second;
00106 if (firstOcc) iref_ass+=references;
00107 if (references<2){
00108 cout << "*** Only 1 ref, vol: " << (*i)->volumeno << " # "
00109 << (*i)->copyno << " side: " << side << endl;
00110 }
00111 } else {
00112 iref_nass+=references;
00113 if (references>1){
00114 cout << "*** Ref_nass >1 " <<endl;
00115 }
00116 }
00117 }
00118 }
00119 iunique = ptrs.size();
00120
00121 cout << " volumes " << ivolumes << endl
00122 << " surfaces " << isurfaces << endl
00123 << " assigned " << iassigned << endl
00124 << " unique " << iunique << endl
00125 << " iref_ass " << iref_ass << endl
00126 << " iref_nass " << iref_nass << endl;
00127 }
00128
00129
00130 void MagGeoBuilderFromDDD::build(const DDCompactView & cpva)
00131 {
00132
00133 DDExpandedView fv(cpva);
00134
00135 if (debug) cout << "**********************************************************" <<endl;
00136
00137
00138 map<string, MagProviderInterpol*> bInterpolators;
00139 map<string, MagProviderInterpol*> eInterpolators;
00140
00141
00142 int bVolCount = 0;
00143 int eVolCount = 0;
00144
00145 if (fv.logicalPart().name().name()!="MAGF") {
00146 std::string topNodeName(fv.logicalPart().name().name());
00147
00148
00149 bool doSubDets = fv.firstChild();
00150
00151 bool go=true;
00152 while(go&& doSubDets) {
00153 if (fv.logicalPart().name().name()=="MAGF")
00154 break;
00155 else
00156 go = fv.nextSibling();
00157 }
00158 if (!go) {
00159 throw cms::Exception("NoMAGFinDDD")<<" Neither the top node, nor any child node of the DDCompactView is \"MAGF\" but the top node is instead \""<<topNodeName<<"\"";
00160 }
00161 }
00162
00163 if (debug) { cout << endl << "*** MAGF: " << fv.geoHistory() << endl
00164 << "translation: " << fv.translation() << endl
00165 << " rotation: " << fv.rotation() << endl;
00166 }
00167
00168 bool doSubDets = fv.firstChild();
00169 while (doSubDets){
00170
00171 string name = fv.logicalPart().name().name();
00172 if (debug) cout << endl << "Name: " << name << endl
00173 << " " << fv.geoHistory() <<endl;
00174
00175
00176
00177
00178
00179
00180
00181 bool expand = false;
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 volumeHandle* v = new volumeHandle(fv, expand);
00200
00201 if (theGridFiles.get()) {
00202 int key = (v->volumeno)*100+v->copyno;
00203 TableFileMap::const_iterator itable = theGridFiles->find(key);
00204 if (itable == theGridFiles->end()) {
00205 key = (v->volumeno)*100;
00206 itable = theGridFiles->find(key);
00207 }
00208
00209 if (itable != theGridFiles->end()) {
00210 string magFile = (*itable).second.first;
00211 stringstream conv;
00212 string svol, ssec;
00213 conv << setfill('0') << setw(3) << v->volumeno << " " << setw(2) << v->copyno;
00214 conv >> svol >> ssec;
00215 boost::replace_all(magFile, "[v]",svol);
00216 boost::replace_all(magFile, "[s]",ssec);
00217 int masterSector = (*itable).second.second;
00218 if (masterSector==0) masterSector=v->copyno;
00219 v->magFile = magFile;
00220 v->masterSector = masterSector;
00221 } else {
00222 edm::LogError("MagGeoBuilderFromDDDbuild") << "ERROR: no table spec found for V " << v->volumeno << ":" << v->copyno;
00223 }
00224 }
00225
00226
00227
00228 float Z = v->center().z();
00229 float R = v->center().perp();
00230
00231
00232
00233
00234
00235
00236
00237 if ((fabs(Z)<647. || (R>350. && fabs(Z)<662.)) &&
00238 !(fabs(Z)>480 && R<172)
00239
00240
00241
00242 ) {
00243 if (debug) cout << " (Barrel)" <<endl;
00244 bVolumes.push_back(v);
00245
00246
00247
00248
00249
00250 if (v->copyno==v->masterSector) {
00251 buildInterpolator(v, bInterpolators);
00252 ++bVolCount;
00253 }
00254 } else {
00255 if (debug) cout << " (Endcaps)" <<endl;
00256 eVolumes.push_back(v);
00257 if (v->copyno==v->masterSector) {
00258 buildInterpolator(v, eInterpolators);
00259 ++eVolCount;
00260 }
00261 }
00262
00263 doSubDets = fv.nextSibling();
00264 }
00265
00266 if (debug) {
00267 cout << "Number of volumes (barrel): " << bVolumes.size() <<endl
00268 << "Number of volumes (endcap): " << eVolumes.size() <<endl;
00269 cout << "**********************************************************" <<endl;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278 if (debug) {
00279 cout << "-----------------------" << endl;
00280 cout << "SUMMARY: Barrel " << endl;
00281 summary(bVolumes);
00282
00283 cout << endl << "SUMMARY: Endcaps " << endl;
00284 summary(eVolumes);
00285 cout << "-----------------------" << endl;
00286 }
00287
00288
00289
00290
00291
00292 vector<bLayer> layers;
00293 precomputed_value_sort(bVolumes.begin(), bVolumes.end(), ExtractRN());
00294
00295
00296 const float resolution = 1.;
00297 float rmin = bVolumes.front()->RN()-resolution;
00298 float rmax = bVolumes.back()->RN()+resolution;
00299 ClusterizingHistogram hisR( int((rmax-rmin)/resolution) + 1, rmin, rmax);
00300
00301 if (debug) cout << " R layers: " << rmin << " " << rmax << endl;
00302
00303 handles::const_iterator first = bVolumes.begin();
00304 handles::const_iterator last = bVolumes.end();
00305
00306 for (handles::const_iterator i=first; i!=last; ++i){
00307 hisR.fill((*i)->RN());
00308 }
00309 vector<float> rClust = hisR.clusterize(resolution);
00310
00311 handles::const_iterator ringStart = first;
00312 handles::const_iterator separ = first;
00313
00314 for (unsigned int i=0; i<rClust.size() - 1; ++i) {
00315 if (debug) cout << " Layer at RN = " << rClust[i];
00316 float rSepar = (rClust[i] + rClust[i+1])/2.f;
00317 while ((*separ)->RN() < rSepar) ++separ;
00318
00319 bLayer thislayer(ringStart, separ);
00320 layers.push_back(thislayer);
00321 ringStart = separ;
00322 }
00323 {
00324 if (debug) cout << " Layer at RN = " << rClust.back();
00325 bLayer thislayer(separ, last);
00326 layers.push_back(thislayer);
00327 }
00328
00329 if (debug) cout << "Barrel: Found " << rClust.size() << " clusters in R, "
00330 << layers.size() << " layers " << endl << endl;
00331
00332
00333
00334
00335 vector<eSector> sectors;
00336
00337
00338 float phireso = 0.05;
00339 ClusterizingHistogram hisPhi( int((Geom::ftwoPi())/phireso) + 1,
00340 -Geom::fpi(), Geom::fpi());
00341
00342 for (handles::const_iterator i=eVolumes.begin(); i!=eVolumes.end(); ++i){
00343 hisPhi.fill((*i)->minPhi());
00344 }
00345 vector<float> phiClust = hisPhi.clusterize(phireso);
00346 int nESectors = phiClust.size();
00347 if (debug && (nESectors%12)!=0) cout << "ERROR: unexpected # of sectors: " << nESectors << endl;
00348
00349
00350 precomputed_value_sort(eVolumes.begin(), eVolumes.end(), ExtractPhi());
00351
00352
00353 for (int i = 0; i<nESectors; ++i) {
00354 int offset = eVolumes.size()/nESectors;
00355 if (debug) cout << " Sector at phi = "
00356 << (*(eVolumes.begin()+((i)*offset)))->center().phi()
00357 << endl;
00358 sectors.push_back(eSector(eVolumes.begin()+((i)*offset),
00359 eVolumes.begin()+((i+1)*offset)));
00360 }
00361
00362 if (debug) cout << "Endcap: Found "
00363 << sectors.size() << " sectors " << endl;
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 buildMagVolumes(bVolumes, bInterpolators);
00406
00407
00408 for (vector<bLayer>::const_iterator ilay = layers.begin();
00409 ilay!= layers.end(); ++ilay) {
00410 mBLayers.push_back((*ilay).buildMagBLayer());
00411 }
00412
00413 if (debug) {
00414 cout << "*** BARREL ********************************************" << endl
00415 << "Number of different volumes = " << bVolCount << endl
00416 << "Number of interpolators built = " << bInterpolators.size() << endl
00417 << "Number of MagBLayers built = " << mBLayers.size() << endl;
00418
00419 testInside(bVolumes);
00420 }
00421
00422
00423
00424 buildMagVolumes(eVolumes, eInterpolators);
00425
00426
00427 for (vector<eSector>::const_iterator isec = sectors.begin();
00428 isec!= sectors.end(); ++isec) {
00429 mESectors.push_back((*isec).buildMagESector());
00430 }
00431
00432 if (debug) {
00433 cout << "*** ENDCAP ********************************************" << endl
00434 << "Number of different volumes = " << eVolCount << endl
00435 << "Number of interpolators built = " << eInterpolators.size() << endl
00436 << "Number of MagESector built = " << mESectors.size() << endl;
00437
00438 testInside(eVolumes);
00439 }
00440 }
00441
00442
00443 void MagGeoBuilderFromDDD::buildMagVolumes(const handles & volumes, map<string, MagProviderInterpol*> & interpolators) {
00444
00445 for (handles::const_iterator vol=volumes.begin(); vol!=volumes.end();
00446 ++vol){
00447 const MagProviderInterpol* mp = 0;
00448 if (interpolators.find((*vol)->magFile)!=interpolators.end()) {
00449 mp = interpolators[(*vol)->magFile];
00450 } else {
00451 edm::LogError("MagGeoBuilderFromDDDbuildMagVolumes") << "No interpolator found for file " << (*vol)->magFile
00452 << " vol: " << (*vol)->volumeno << "\n" << interpolators.size() <<endl;
00453 }
00454
00455
00456
00457 int key = ((*vol)->volumeno)*100+(*vol)->copyno;
00458 map<int, double>::const_iterator isf = theScalingFactors.find(key);
00459 if (isf == theScalingFactors.end()) {
00460 key = ((*vol)->volumeno)*100;
00461 isf = theScalingFactors.find(key);
00462 }
00463
00464 double sf = 1.;
00465 if (isf != theScalingFactors.end()) {
00466 sf = (*isf).second;
00467
00468 edm::LogInfo("MagneticField|VolumeBasedMagneticFieldESProducer") << "Applying scaling factor " << sf << " to "<< (*vol)->volumeno << "["<< (*vol)->copyno << "] (key:" << key << ")" << endl;
00469 }
00470
00471 const GloballyPositioned<float> * gpos = (*vol)->placement();
00472 (*vol)->magVolume = new MagVolume6Faces(gpos->position(),
00473 gpos->rotation(),
00474 (*vol)->shape(),
00475 (*vol)->sides(),
00476 mp, sf);
00477
00478 if ((*vol)->copyno==(*vol)->masterSector) {
00479 (*vol)->magVolume->ownsFieldProvider(true);
00480 }
00481
00482 (*vol)->magVolume->setIsIron((*vol)->isIron());
00483
00484
00485 (*vol)->magVolume->volumeNo = (*vol)->volumeno;
00486 (*vol)->magVolume->copyno = (*vol)->copyno;
00487 }
00488 }
00489
00490
00491 void MagGeoBuilderFromDDD::buildInterpolator(const volumeHandle * vol, map<string, MagProviderInterpol*> & interpolators){
00492
00493
00494 double masterSectorPhi = (vol->masterSector-1)*Geom::pi()/6.;
00495
00496 if (debug) {
00497 cout << "Building interpolator from "
00498 << vol->volumeno << " copyno " << vol->copyno
00499 << " at " << vol->center()
00500 << " phi: " << vol->center().phi()
00501 << " file: " << vol->magFile
00502 << endl;
00503
00504 if ( fabs(vol->center().phi() - masterSectorPhi) > Geom::pi()/9.) {
00505 cout << "***WARNING wrong sector? " << endl;
00506 }
00507 }
00508
00509 if (tableSet == "fake" || vol->magFile== "fake") {
00510 interpolators[vol->magFile] = new magneticfield::FakeInterpolator();
00511 return;
00512 }
00513
00514 string fullPath;
00515
00516 try {
00517 edm::FileInPath mydata("MagneticField/Interpolation/data/"+tableSet+"/"+vol->magFile);
00518 fullPath = mydata.fullPath();
00519 } catch (edm::Exception& exc) {
00520 cerr << "MagGeoBuilderFromDDD: exception in reading table; " << exc.what() << endl;
00521 if (!debug) throw;
00522 return;
00523 }
00524
00525
00526 try{
00527 if (vol->toExpand()){
00528
00529
00530
00531 } else {
00532
00533
00534
00535 GloballyPositioned<float> rf = *(vol->placement());
00536
00537 if (vol->masterSector != 1) {
00538 typedef Basic3DVector<float> Vector;
00539
00540 GloballyPositioned<float>::RotationType rot(Vector(0,0,1), -masterSectorPhi);
00541 Vector vpos(vol->placement()->position());
00542
00543
00544 rf = GloballyPositioned<float>(GloballyPositioned<float>::PositionType(rot.multiplyInverse(vpos)), vol->placement()->rotation()*rot);
00545 }
00546
00547 interpolators[vol->magFile] =
00548 MFGridFactory::build( fullPath, rf);
00549 }
00550 } catch (MagException& exc) {
00551 cout << exc.what() << endl;
00552 interpolators.erase(vol->magFile);
00553 if (!debug) throw;
00554 return;
00555 }
00556
00557
00558 if (debug) {
00559
00560 const MagVolume6Faces tempVolume(vol->placement()->position(),
00561 vol->placement()->rotation(),
00562 vol->shape(),
00563 vol->sides(),
00564 interpolators[vol->magFile]);
00565
00566 const MFGrid* grid = dynamic_cast<const MFGrid*>(interpolators[vol->magFile]);
00567 if (grid!=0) {
00568
00569 Dimensions sizes = grid->dimensions();
00570 cout << "Grid has 3 dimensions "
00571 << " number of nodes is " << sizes.w << " " << sizes.h
00572 << " " << sizes.d << endl;
00573
00574 const double tolerance = 0.03;
00575
00576
00577 size_t dumpCount = 0;
00578 for (int j=0; j < sizes.h; j++) {
00579 for (int k=0; k < sizes.d; k++) {
00580 for (int i=0; i < sizes.w; i++) {
00581 MFGrid::LocalPoint lp = grid->nodePosition( i, j, k);
00582 if (! tempVolume.inside(lp, tolerance)) {
00583 if (++dumpCount < 2) {
00584 MFGrid::GlobalPoint gp = tempVolume.toGlobal(lp);
00585 cout << "GRID ERROR: " << i << " " << j << " " << k
00586 << " local: " << lp
00587 << " global: " << gp
00588 << " R= " << gp.perp() << " phi=" << gp.phi() << endl;
00589 }
00590 }
00591 }
00592 }
00593 }
00594
00595 cout << "Volume:" << vol->volumeno << " : Number of grid points outside the MagVolume: " << dumpCount << "/" << sizes.w*sizes.h*sizes.d << endl;
00596 }
00597 }
00598 }
00599
00600
00601
00602 void MagGeoBuilderFromDDD::testInside(handles & volumes) {
00603
00604 cout << "--------------------------------------------------" << endl;
00605 cout << " inside(center) test" << endl;
00606 for (handles::const_iterator vol=volumes.begin(); vol!=volumes.end();
00607 ++vol){
00608 for (handles::const_iterator i=volumes.begin(); i!=volumes.end();
00609 ++i){
00610 if ((*i)==(*vol)) continue;
00611
00612 if ((*i)->magVolume->inside((*vol)->center())) {
00613 cout << "*** ERROR: center of V " << (*vol)->volumeno << " is inside V "
00614 << (*i)->volumeno <<endl;
00615 }
00616 }
00617
00618 if ((*vol)->magVolume->inside((*vol)->center())) {
00619 cout << "V " << (*vol)->volumeno << " OK " << endl;
00620 } else {
00621 cout << "*** ERROR: center of volume is not inside it, "
00622 << (*vol)->volumeno << endl;
00623 }
00624 }
00625 cout << "--------------------------------------------------" << endl;
00626 }
00627
00628
00629 vector<MagBLayer*> MagGeoBuilderFromDDD::barrelLayers() const{
00630 return mBLayers;
00631 }
00632
00633 vector<MagESector*> MagGeoBuilderFromDDD::endcapSectors() const{
00634 return mESectors;
00635 }
00636
00637 vector<MagVolume6Faces*> MagGeoBuilderFromDDD::barrelVolumes() const{
00638 vector<MagVolume6Faces*> v;
00639 v.reserve(bVolumes.size());
00640 for (handles::const_iterator i=bVolumes.begin();
00641 i!=bVolumes.end(); ++i){
00642 v.push_back((*i)->magVolume);
00643 }
00644 return v;
00645 }
00646
00647 vector<MagVolume6Faces*> MagGeoBuilderFromDDD::endcapVolumes() const{
00648 vector<MagVolume6Faces*> v;
00649 v.reserve(eVolumes.size());
00650 for (handles::const_iterator i=eVolumes.begin();
00651 i!=eVolumes.end(); ++i){
00652 v.push_back((*i)->magVolume);
00653 }
00654 return v;
00655 }
00656
00657
00658 float MagGeoBuilderFromDDD::maxR() const{
00659
00660 return 900.;
00661 }
00662
00663 float MagGeoBuilderFromDDD::maxZ() const{
00664
00665 if (geometryVersion>=120812) return 2000.;
00666 else return 1600.;
00667 }
00668
00669
00670 void MagGeoBuilderFromDDD::setScaling(const std::vector<int>& keys,
00671 const std::vector<double>& values)
00672 {
00673 if (keys.size() != values.size()) {
00674 throw cms::Exception("InvalidParameter") << "Invalid field scaling parameters 'scalingVolumes' and 'scalingFactors' ";
00675 }
00676 for (unsigned int i=0; i<keys.size(); ++i) {
00677 theScalingFactors[keys[i]] = values[i];
00678 }
00679 }
00680
00681
00682 void MagGeoBuilderFromDDD::setGridFiles(auto_ptr<TableFileMap> gridFiles){
00683 theGridFiles=gridFiles;
00684 }
00685
00686