CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/src/Geometry/CSCGeometryBuilder/src/CSCGeometryBuilder.cc

Go to the documentation of this file.
00001 #include "CSCGeometryBuilder.h"
00002 //#include <CondFormats/GeometryObjects/interface/CSCRecoDigiParameters.h>
00003 //#include <CondFormats/GeometryObjects/interface/RecoIdealGeometry.h>
00004 
00005 #include <Geometry/CSCGeometry/interface/CSCGeometry.h>
00006 
00007 #include <DataFormats/DetId/interface/DetId.h>
00008 #include <DataFormats/MuonDetId/interface/CSCDetId.h>
00009 #include <Geometry/CSCGeometry/src/CSCWireGroupPackage.h>
00010 
00011 #include <FWCore/MessageLogger/interface/MessageLogger.h>
00012 
00013 #include <iostream>
00014 #include <iomanip>
00015 #include <algorithm>
00016 #include <vector>
00017 
00018 CSCGeometryBuilder::CSCGeometryBuilder() : myName("CSCGeometryBuilder"){}
00019 
00020 
00021 CSCGeometryBuilder::~CSCGeometryBuilder(){}
00022 
00023 
00024 void CSCGeometryBuilder::build( boost::shared_ptr<CSCGeometry> theGeometry
00025                                 , const RecoIdealGeometry& rig
00026                                 , const CSCRecoDigiParameters& cscpars ) {
00027 
00028   //  CSCGeometry* theGeometry = new CSCGeometry;
00029 
00030   std::vector<float> fpar;
00031   std::vector<float> gtran;
00032   std::vector<float> grmat;
00033   std::vector<float> fupar;
00034   std::vector<double>::const_iterator it, endIt;
00035   const std::vector<DetId>& detids(rig.detIds());
00036 
00037   for ( size_t idt = 0; idt < detids.size(); ++idt) {
00038     CSCDetId detid = CSCDetId( detids[idt] );
00039     //    int jendcap  = detid.endcap();
00040     int jstation = detid.station();
00041     int jring    = detid.ring();
00042     //    int jchamber = detid.chamber();
00043 
00044     endIt = rig.shapeEnd(idt);
00045     fpar.clear();
00046     for ( it = rig.shapeStart(idt); it != endIt; ++it) {
00047       fpar.push_back( (float)(*it) );
00048     }
00049 
00050     gtran.clear();
00051     endIt = rig.tranEnd(idt);
00052     for ( it = rig.tranStart(idt); it != endIt; ++it ) {
00053       gtran.push_back((float)(*it));
00054     }
00055     grmat.clear();
00056     endIt = rig.rotEnd(idt);
00057     for ( it = rig.rotStart(idt) ; it != endIt; ++it ) {
00058       grmat.push_back((float)(*it));
00059     }
00060 
00061     // get the chamber type from existing info
00062     int chamberType = CSCChamberSpecs::whatChamberType( jstation, jring );
00063     //    std::cout << "Chamber type = " << chamberType << std::endl;
00064     size_t cs = 0;
00065     //       assert ( cscpars.pCSCDetIds.size() != 0 );
00066     assert ( cscpars.pChamberType.size() != 0 );
00067     //       while (cs < cscpars.pCSCDetIds.size() && detid != cscpars.pCSCDetIds[cs]) {
00068     while (cs < cscpars.pChamberType.size() && chamberType != cscpars.pChamberType[cs]) {
00069       ++cs;
00070     }
00071     //       assert ( cs != cscpars.pCSCDetIds.size() );
00072     assert ( cs != cscpars.pChamberType.size() );
00073       
00074     // check the existence of the specs for this type WHY? Remove it...
00075     //    const CSCChamberSpecs* aSpecs = theGeometry->findSpecs( chamberType );
00076     size_t fu, numfuPars;
00077     CSCWireGroupPackage wg;
00078     fu = cscpars.pUserParOffset[cs];
00079     numfuPars = fu + 1 + size_t(cscpars.pfupars[fu]);
00080 
00081     // upars from db are now uparvals + wg info so we need to unwrap only part here first...
00082     LogTrace(myName) << myName << ": I think I have " << cscpars.pUserParSize[cs] << " values in pfupars (uparvals)." << std::endl;
00083     LogTrace(myName) << myName << ": For fupar I will start at " << cscpars.pUserParOffset[cs] + 1 
00084                      << " in pfupars and go to " << numfuPars << "." << std::endl;
00085     //    if ( aSpecs == 0 ) { 
00086       for ( ++fu; fu < numfuPars; ++fu ) {
00087         LogTrace(myName) << myName << ": pfupars[" << fu << "]=" << cscpars.pfupars[fu] << std::endl;
00088         fupar.push_back(cscpars.pfupars[fu]);
00089       }
00090 //     } else {
00091 //       fu = fu + numfuPars + 1;
00092 //     }
00093     // now, we need to start from "here" at fu to go on and build wg...
00094     wg.wireSpacing = cscpars.pfupars[fu++];
00095     wg.alignmentPinToFirstWire = cscpars.pfupars[fu++];
00096     wg.numberOfGroups = int(cscpars.pfupars[fu++]);
00097     wg.narrowWidthOfWirePlane = cscpars.pfupars[fu++];
00098     wg.wideWidthOfWirePlane = cscpars.pfupars[fu++];
00099     wg.lengthOfWirePlane = cscpars.pfupars[fu++];
00100     size_t numgrp = static_cast<size_t>(cscpars.pfupars[fu]);
00101     size_t maxFu = fu + 1 + numgrp;
00102     fu++;
00103     for ( ;fu < maxFu; ++fu ) {
00104       wg.wiresInEachGroup.push_back(int(cscpars.pfupars[fu]));
00105     } 
00106     maxFu = fu + numgrp;
00107     //stupid comment    // MEC: 2008-04-30: decided I need to have wg every time unless whole wg idea is re-worked.
00108     //       std::cout << " fu = " << fu << " going to maxFu = " << maxFu << std::endl;
00109     for ( ;fu < maxFu; ++fu ) {
00110       wg.consecutiveGroups.push_back(int(cscpars.pfupars[fu]));
00111     } 
00112           
00113     if ( wg.numberOfGroups != 0 ) {
00114       LogTrace(myName) << myName  << ": TotNumWireGroups     = " << wg.numberOfGroups ;
00115       LogTrace(myName) << myName  << ": WireSpacing          = " << wg.wireSpacing ;
00116       LogTrace(myName) << myName  << ": AlignmentPinToFirstWire = " << wg.alignmentPinToFirstWire ;
00117       LogTrace(myName) << myName  << ": Narrow width of wire plane = " << wg.narrowWidthOfWirePlane ;
00118       LogTrace(myName) << myName  << ": Wide width of wire plane = " << wg.wideWidthOfWirePlane ;
00119       LogTrace(myName) << myName  << ": Length in y of wire plane = " << wg.lengthOfWirePlane ;
00120       LogTrace(myName) << myName  << ": wg.consecutiveGroups.size() = " << wg.consecutiveGroups.size() ;
00121       LogTrace(myName) << myName  << ": wg.wiresInEachGroup.size() = " << wg.wiresInEachGroup.size() ;
00122       LogTrace(myName) << myName  << ": \tNumGroups\tWiresInGroup" ;
00123       for (size_t i = 0; i < wg.consecutiveGroups.size(); i++) {
00124         LogTrace(myName) << myName  << " \t" << wg.consecutiveGroups[i] << "\t\t" << wg.wiresInEachGroup[i] ;
00125       }
00126     } else {
00127       LogTrace(myName) << myName  << ": DDD is MISSING SpecPars for wire groups" ;
00128     }
00129     LogTrace(myName) << myName << ": end of wire group info. " ;
00130       
00131     //      CSCWireGroupPackage wg = cscpars.pWGPs[cs];
00132     // Are we going to apply centre-to-intersection offsets, even if values exist in the specs file?
00133     if ( !theGeometry->centreTIOffsets() ) fupar[30] = 0.;  // reset to zero if flagged 'off'
00134       
00135     buildChamber (theGeometry, detid, fpar, fupar, gtran, grmat, wg ); //, cscpars.pWGPs[cs] );
00136     fupar.clear();
00137   }
00138   //    return theGeometry;  
00139 }
00140 
00141 void CSCGeometryBuilder::buildChamber (  
00142                                        boost::shared_ptr<CSCGeometry> theGeometry // the geometry container
00143                                        , CSCDetId chamberId                         // the DetId for this chamber
00144                                        , const std::vector<float>& fpar           // volume parameters hB, hT. hD, hH   
00145                                        , const std::vector<float>& fupar          // user parameters 
00146                                        , const std::vector<float>& gtran          // translation vector 
00147                                        , const std::vector<float>& grmat          // rotation matrix
00148                                        , const CSCWireGroupPackage& wg            // wire group info
00149                                        ) {
00150 
00151   LogTrace(myName) << myName  << ": entering buildChamber" ;
00152 
00153   int jend   = chamberId.endcap();
00154   int jstat  = chamberId.station();
00155   int jring  = chamberId.ring();
00156   int jch    = chamberId.chamber();
00157   int jlay   = chamberId.layer();
00158 
00159   if (jlay != 0 ) edm::LogWarning(myName) << "Error! CSCGeometryBuilderFromDDD was fed layer id = " << jlay << "\n";
00160 
00161   const size_t kNpar = 4;
00162   if ( fpar.size() != kNpar ) 
00163     edm::LogError(myName) << "Error, expected npar=" 
00164               << kNpar << ", found npar=" << fpar.size() << std::endl;
00165 
00166   LogTrace(myName) << myName  << ":  E" << jend << " S" << jstat << " R" << jring <<
00167     " C" << jch << " L" << jlay ;
00168   LogTrace(myName) << myName  << ": npar=" << fpar.size() << " hB=" << fpar[0] 
00169                   << " hT=" << fpar[1] << " hD=" << fpar[2] << " hH=" << fpar[3] ;
00170   LogTrace(myName) << myName  << ": gtran[0,1,2]=" << gtran[0] << " " << gtran[1] << " " << gtran[2] ;
00171   LogTrace(myName) << myName  << ": grmat[0-8]=" << grmat[0] << " " << grmat[1] << " " << grmat[2] << " "
00172          << grmat[3] << " " << grmat[4] << " " << grmat[5] << " "
00173                   << grmat[6] << " " << grmat[7] << " " << grmat[8] ;
00174   LogTrace(myName) << myName  << ": nupar=" << fupar.size() << " upar[0]=" << fupar[0]
00175                    << " upar[" << fupar.size()-1 << "]=" << fupar[fupar.size()-1];
00176 
00177 
00178   CSCChamber* chamber = const_cast<CSCChamber*>(theGeometry->chamber( chamberId ));
00179   if ( chamber ){
00180   }
00181   else { // this chamber not yet built/stored
00182   
00183     LogTrace(myName) << myName <<": CSCChamberSpecs::build requested for ME" << jstat << jring ;
00184      int chamberType = CSCChamberSpecs::whatChamberType( jstat, jring );
00185      const CSCChamberSpecs* aSpecs = theGeometry->findSpecs( chamberType );
00186 //     //    CSCChamberSpecs* aSpecs = CSCChamberSpecs::specs( chamberType );
00187 //     if ( aSpecs == 0 ) aSpecs = theGeometry->buildSpecs( chamberType, fpar, fupar, wg );
00188     //                 aSpecs = CSCChamberSpecs::build( chamberType, fpar, fupar, wg );
00189     if ( fupar.size() != 0 && aSpecs == 0 ) {
00190       // make new one:
00191       aSpecs = theGeometry->buildSpecs (chamberType, fpar, fupar, wg);
00192     } else if ( fupar.size() == 0 && aSpecs == 0 ) {
00193         std::cout << "SHOULD BE THROW? Error, wg and/or fupar size are 0 BUT this Chamber Spec has not been built!" << std::endl;
00194     }
00195 //  else if (fupar.size() != 0 && aSpecs != 0 ) {
00196 //       std::cout << "SHOULD BE THROW? Error, a Chamber Specs was found AND still the fupar and/or wg were/was non-zero! " << std::endl;
00197 //     }
00198 
00199 
00200    // Build a Transformation out of GEANT gtran and grmat...
00201    // These are used to transform a point in the local reference frame
00202    // of a subdetector to the global frame of CMS by
00203    //         (grmat)^(-1)*local + (gtran)
00204    // The corresponding transformation from global to local is
00205    //         (grmat)*(global - gtran)
00206  
00207     BoundSurface::RotationType aRot( grmat[0], grmat[1], grmat[2], 
00208                                      grmat[3], grmat[4], grmat[5],
00209                                      grmat[6], grmat[7], grmat[8] );
00210 
00211    // This rotation from GEANT considers the detector face as the x-z plane.
00212    // We want this to be the local x-y plane.
00213    // Furthermore, the -z_global endcap has LH local coordinates, since it is built
00214    // in GEANT as a *reflection* of the +z_global endcap.
00215    // So we need to rotate, and in -z flip local x.
00216 
00217    // aRot.rotateAxes will transform aRot in place so that it becomes
00218    // applicable to the new local coordinates: detector face in x-y plane
00219    // looking out along z, in either endcap.
00220 
00221    // The interface for rotateAxes specifies 'new' X,Y,Z but the
00222    // implementation deals with them as the 'old'.
00223 
00224     Basic3DVector<float> oldX( 1., 0.,  0. );
00225     Basic3DVector<float> oldY( 0., 0., -1. );
00226     Basic3DVector<float> oldZ( 0., 1.,  0. );
00227 
00228     if ( gtran[2]<0. ) oldX *= -1; 
00229 
00230     aRot.rotateAxes( oldX, oldY, oldZ );
00231       
00232    // Need to know z of layers w.r.t to z of centre of chamber. 
00233 
00234     float frameThickness     = fupar[31]/10.; // mm -> cm
00235     float gapThickness       = fupar[32]/10.; // mm -> cm
00236     float panelThickness     = fupar[33]/10.; // mm -> cm
00237     float zAverageAGVtoAF    = fupar[34]/10.; // mm -> cm
00238 
00239     float layerThickness = gapThickness; // consider the layer to be the gas gap
00240     float layerSeparation = gapThickness + panelThickness; // centre-to-centre of neighbouring layers
00241 
00242     float chamberThickness = 7.*panelThickness + 6.*gapThickness + 2.*frameThickness ; // chamber frame thickness
00243     float hChamberThickness = chamberThickness/2.; // @@ should match value returned from DDD directly
00244 
00245     // distAverageAGVtoAF is offset between centre of chamber (AF) and (L1+L6)/2 (average AGVs) 
00246     // where AF = AluminumFrame and AGV=ActiveGasVolume (volume names in DDD).
00247     // It is signed based on global z values: zc - (zl1+zl6)/2
00248    
00249     // Local z values w.r.t. AF...
00250     //     z of wires in layer 1 = z_w1 = +/- zAverageAGVtoAF + 2.5*layerSeparation; // layer 1 is at most +ve local z
00251     // The sign in '+/-' depends on relative directions of local and global z. 
00252     // It is '-' if they are the same direction, and '+' if opposite directions.
00253     //     z of wires in layer N   = z_wN = z_w1 - (N-1)*layerSeparation; 
00254     //     z of strips in layer N  = z_sN = z_wN + gapThickness/2.; @@ BEWARE: need to check if it should be '-gapThickness/2' !
00255 
00256     // Set dimensions of trapezoidal chamber volume 
00257     // N.B. apothem is 4th in fpar but 3rd in ctor 
00258 
00259     // hChamberThickness and fpar[2] should be the same - but using the above value at least shows
00260     // how chamber structure works
00261 
00262     //    TrapezoidalPlaneBounds* bounds =  new TrapezoidalPlaneBounds( fpar[0], fpar[1], fpar[3], fpar[2] ); 
00263     TrapezoidalPlaneBounds* bounds =  new TrapezoidalPlaneBounds( fpar[0], fpar[1], fpar[3], hChamberThickness ); 
00264 
00265    // Centre of chamber in z is specified in DDD
00266     Surface::PositionType aVec( gtran[0], gtran[1], gtran[2] ); 
00267 
00268     BoundPlane::BoundPlanePointer plane = BoundPlane::build(aVec, aRot, bounds); 
00269     delete bounds; // bounds cloned by BoundPlane, so we can delete it
00270 
00271     CSCChamber* chamber = new CSCChamber( plane, chamberId, aSpecs );
00272     theGeometry->addChamber( chamber ); 
00273 
00274     LogTrace(myName) << myName << ": Create chamber E" << jend << " S" << jstat 
00275                      << " R" << jring << " C" << jch 
00276                      << " z=" << gtran[2]
00277                      << " t/2=" << fpar[2] << " (DDD) or " << hChamberThickness 
00278                      << " (specs) adr=" << chamber ;
00279 
00280     // Create the component layers of this chamber   
00281     // We're taking the z as the z of the wire plane within the layer (middle of gas gap)
00282 
00283     // Specify global z of layer by offsetting from centre of chamber: since layer 1 
00284     // is nearest to IP in stations 1/2 but layer 6 is nearest in stations 3/4, 
00285     // we need to adjust sign of offset appropriately...
00286     int localZwrtGlobalZ = +1;
00287     if ( (jend==1 && jstat<3 ) || ( jend==2 && jstat>2 ) ) localZwrtGlobalZ = -1;
00288     int globalZ = +1;
00289     if ( jend == 2 ) globalZ = -1;
00290 //     int localZwrtGlobalZ = +1;
00291 //     if ( (jend==1 && jstat<3 ) || ( jend==2 && jstat>2 ) ) localZwrtGlobalZ = -1;
00292 
00293 
00294     LogTrace(myName) << myName << ": layerSeparation=" << layerSeparation
00295                      << ", zAF-zAverageAGV="  << zAverageAGVtoAF
00296                      << ", localZwrtGlobalZ=" << localZwrtGlobalZ
00297                      << ", gtran[2]=" << gtran[2] ;
00298 
00299     for ( short j = 1; j <= 6; ++j ) {
00300 
00301       CSCDetId layerId = CSCDetId( jend, jstat, jring, jch, j );
00302 
00303       // extra-careful check that we haven't already built this layer
00304       const CSCLayer* cLayer = dynamic_cast<const CSCLayer*> (theGeometry->idToDet( layerId ) );
00305 
00306       if ( cLayer == 0 ) {
00307 
00308         // build the layer - need the chamber's specs and an appropriate layer-geometry
00309          const CSCChamberSpecs* aSpecs = chamber->specs();
00310          const CSCLayerGeometry* geom = 
00311                     (j%2 != 0) ? aSpecs->oddLayerGeometry( jend ) : 
00312                                  aSpecs->evenLayerGeometry( jend );
00313 
00314         // Build appropriate BoundPlane, based on parent chamber, with gas gap as thickness
00315 
00316         // centre of chamber is at global z = gtran[2]
00317         float zlayer = gtran[2] - globalZ*zAverageAGVtoAF + localZwrtGlobalZ*(3.5-j)*layerSeparation;
00318 
00319         BoundSurface::RotationType chamberRotation = chamber->surface().rotation();
00320         BoundPlane::PositionType layerPosition( gtran[0], gtran[1], zlayer );
00321         //        TrapezoidalPlaneBounds* bounds = new TrapezoidalPlaneBounds( *geom );
00322         //      std::vector<float> dims = bounds->parameters(); // returns hb, ht, d, a
00323         std::vector<float> dims = geom->parameters(); // returns hb, ht, d, a
00324         dims[2] = layerThickness/2.; // half-thickness required and note it is 3rd value in vector
00325         //        delete bounds;        
00326         //        bounds = new TrapezoidalPlaneBounds( dims[0], dims[1], dims[3], dims[2] );
00327         TrapezoidalPlaneBounds* bounds = new TrapezoidalPlaneBounds( dims[0], dims[1], dims[3], dims[2] );
00328         BoundPlane::BoundPlanePointer plane = BoundPlane::build(layerPosition, chamberRotation, bounds);
00329         delete bounds;
00330 
00331         CSCLayer* layer = new CSCLayer( plane, layerId, chamber, geom );
00332 
00333         LogTrace(myName) << myName << ": Create layer E" << jend << " S" << jstat 
00334                     << " R" << jring << " C" << jch << " L" << j
00335                     << " z=" << zlayer
00336                          << " t=" << layerThickness << " or " << layer->surface().bounds().thickness()
00337                     << " adr=" << layer << " layerGeom adr=" << geom ;
00338 
00339         chamber->addComponent(j, layer); 
00340         theGeometry->addLayer( layer );
00341       }
00342       else {
00343         edm::LogError(myName) << ": ERROR, layer " << j <<
00344             " for chamber = " << ( chamber->id() ) <<
00345             " already exists: layer address=" << cLayer <<
00346             " chamber address=" << chamber << "\n";
00347       }
00348 
00349     } // layer construction within chamber
00350   } // chamber construction
00351 }