Report problems to ATLAS LXR Team (with time and IP address indicated)

The LXR Cross Referencer

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Architecture: linux ]
Version: head ] [ nightly ] [ GaudiDev ]
  Links to LXR source navigation pages for stable releases [ 12.*.* ]   [ 13.*.* ]   [ 14.*.* ]   [ 15.*.* ] 

001 #include "GaudiKernel/MsgStream.h"
002 #include "AthenaKernel/getMessageSvc.h"
003 //
004 #include "MuonGeoModel/MuonChamber.h"
005 #include "MuonGeoModel/Position.h"
006 #include "MuonReadoutGeometry/MuonStation.h"
007 #include "MuonGeoModel/FPVMAP.h"
008 #include "MuonReadoutGeometry/MuonDetectorManager.h"
009 #include "MuonGeoModel/Station.h"
010 #include "MuonGeoModel/Csc.h"
011 #include "MuonGeoModel/Mdt.h"
012 #include "MuonGeoModel/Tgc.h"
013 #include "MuonGeoModel/Rpc.h"
014 #include "MuonGeoModel/Ded.h"
015 #include "MuonGeoModel/Sup.h"
016 #include "MuonGeoModel/Spacer.h"
017 #include "MuonGeoModel/SpacerBeam.h"
018 #include "MuonGeoModel/Cutout.h"
019 #include "MuonReadoutGeometry/GlobalUtilities.h"
020 //
021 #include "MuonGeoModel/StandardComponent.h"
022 #include "MuonGeoModel/LbiComponent.h"
023 #include "MuonGeoModel/CbmComponent.h"
024 #include "MuonGeoModel/MdtComponent.h"
025 #include "MuonGeoModel/RpcComponent.h"
026 #include "MuonGeoModel/SupComponent.h"
027 #include "MuonGeoModel/TgcComponent.h"
028 #include "MuonGeoModel/CscComponent.h"
029 #include "MuonReadoutGeometry/MdtReadoutElement.h"
030 #include "MuonReadoutGeometry/RpcReadoutElement.h"
031 #include "MuonReadoutGeometry/TgcReadoutElement.h"
032 #include "MuonReadoutGeometry/CscReadoutElement.h"
033 // just to check subtype, cutout:
034 #include "MuonGeoModel/MYSQL.h"
035 #include "MuonGeoModel/CSC_Technology.h"
036 #include "MuonGeoModel/MDT_Technology.h"
037 #include "MuonGeoModel/RPC_Technology.h"
038 #include "MuonGeoModel/TGC_Technology.h"
039 #include "MuonGeoModel/LBI_Technology.h"
040 //
041 #include "MuonIdHelpers/MdtIdHelper.h"
042 #include "MuonIdHelpers/RpcIdHelper.h"
043 #include "MuonIdHelpers/TgcIdHelper.h"
044 #include "MuonIdHelpers/CscIdHelper.h"
045 //
046 #include "GeoModelKernel/GeoBox.h"
047 #include "GeoModelKernel/GeoTube.h"
048 #include "GeoModelKernel/GeoTrd.h"
049 #include "GeoModelKernel/GeoPhysVol.h"
050 #include "GeoModelKernel/GeoFullPhysVol.h"
051 #include "GeoModelKernel/GeoLogVol.h"
052 #include "GeoModelKernel/GeoMaterial.h"
053 #include "GeoModelKernel/GeoNameTag.h"
054 #include "GeoModelKernel/GeoSerialDenominator.h"
055 #include "GeoModelKernel/GeoTransform.h"
056 #include "GeoModelKernel/GeoShapeShift.h"
057 #include "GeoModelKernel/GeoShapeSubtraction.h" 
058 #include "GeoModelKernel/GeoShapeUnion.h"
059 #include "GeoModelKernel/GeoShapeIntersection.h"   
060 #include "GeoModelKernel/GeoIdentifierTag.h"
061 #include "CLHEP/Geometry/Transform3D.h"
062 #include <vector>
063 #include <fstream>
064 #include <iomanip>
065 
066 #define RPCON true
067 #define useAssemblies false
068 
069 namespace MuonGM {
070 
071 
072 MuonChamber::MuonChamber(Station *s): DetectorElement(s->GetName())
073 {
074 
075   width = s->GetWidth1();
076   longWidth = s->GetWidth2();
077   thickness = s->GetThickness();
078   length=s->GetLength();
079   station = s;
080   // CSL envelope is too small for its components - enlarge it slightly
081   std::string stname(station->GetName(), 0, 3);
082   if (stname == "CSL") longWidth *= 1.015;
083   
084   m_msgSvc = Athena::getMessageSvc();
085   m_enableFineClashFixing = 0;
086 }
087 
088 
089 GeoVPhysVol*
090 MuonChamber::build(MuonDetectorManager* m_manager, int zi,
091                                 int fi, bool is_mirrored, bool& isAssembly)
092 {
093   MsgStream log(m_msgSvc, "MuGM:MuonChamber");
094   bool m_debug   = log.level() <= MSG::DEBUG;
095   bool m_verbose = log.level() <= MSG::VERBOSE;
096   if (m_verbose) std::cout << " Building a MuonChamber for station "
097                            << station->GetName() << " at zi, fi "
098                            << zi << " " << fi+1 << " is_mirrored " << is_mirrored
099                            << " is assembly = " << isAssembly << std::endl;
100   std::string stname(station->GetName(), 0, 3);
101   MYSQL* mysql=MYSQL::GetPointer();
102   MDT* m = (MDT*)mysql->GetATechnology("MDT0");
103   double halfpitch = (m->pitch)/2.;
104     
105   std::string stName = station->GetName();
106   const MdtIdHelper* mdt_id  = m_manager->mdtIdHelper();
107   int stationType = mdt_id->stationNameIndex(stName.substr(0,3));
108   bool is_barrel = (stName.substr(0,1)=="B");
109 
110   std::string geometry_version=m_manager->geometryVersion();    
111     
112   double extratop    = station->GetExtraTopThickness();
113   double extrabottom = station->GetExtraBottomThickness();
114   double totthick =  thickness + extratop + extrabottom;
115 
116   GeoTrd* maintrd;
117   maintrd = new GeoTrd(totthick/2, totthick/2, width/2, 
118                            longWidth/2, length/2);
119   if (length <= 0) std::cerr << " Invalid length " << length << " for station "
120                              << station->GetName() << " fi/zi " << fi+1 
121                              << "/" << zi << std::endl;
122   if (m_verbose) log << MSG::VERBOSE << " MuonChamber size thick,w,lw,l "
123                      << totthick << ", " << width << ", " << longWidth
124                      << ", " << length << std::endl;
125 
126   const GeoShape* strd = 0;
127   double dx = 0.;
128   if ( (extratop + extrabottom) != 0.) {
129     // sup on top & bottom
130     dx = extratop/2. - extrabottom/2.;
131     if (m_verbose) log<<MSG::VERBOSE<<" station name "<<station->GetName()<<" extra top, bottom, dx = "
132                       <<extratop<<" "<<extrabottom<<endreq;
133     strd = & ( (*maintrd) << HepTranslate3D(dx, 0., 0.) );
134   } else {
135     strd =  maintrd;
136   }
137 
138   double amdbOrigine_along_length = station->getAmdbOrigine_along_length();
139   double amdbOrigine_along_thickness = station->getAmdbOrigine_along_thickness();
140 
141   // Fix clash of EIS1 and CSS1.  Cut out upper corner of CSS1 envelope (along long width)
142   if (stname == "CSS") {
143     StandardComponent* comp = 0;
144     double clen = 0;
145     double cthick = 0;
146     double cypos = 0;
147     double cxpos = 0;
148     for (int i = 0; i < station->GetNrOfComponents(); i++) {
149       comp = (StandardComponent*)station->GetComponent(i);
150       if ((comp->name).substr(0,3) == "CSC") {
151         clen = comp->dy;
152         cthick = comp->GetThickness();
153         cypos = clen - comp->posy + 1.0 - length/2.;
154         cxpos = -totthick/2. + comp->posz + cthick/2. + 0.1;
155         break;
156       }
157     }
158     GeoShape* box = new GeoBox(cthick/2., longWidth/2., (length-clen)/2.);
159     box->ref();
160     strd = &(strd->subtract( (*box) << HepTranslate3D(cxpos, 0., cypos) ) );
161     box->unref();
162   }
163 
164   if (m_enableFineClashFixing > 0) {
165     // Mother volume modifications for specific chambers
166 
167     // Fix clashes of non-cutout BMS with BTWingRib
168     if ((stname == "BMS" && std::abs(zi) == 5) || 
169         (stname == "BMS" && std::abs(zi) == 1 && fi != 3)) {
170       StandardComponent* comp = 0;
171       double cutlen = 0.;
172       double cutthick = 0.;
173       double top_edge = 0.;
174       for (int i = station->GetNrOfComponents() - 2; i > -1; i--) {
175         comp = (StandardComponent*)station->GetComponent(i);
176         top_edge = comp->posy + comp->dy;
177         cutlen = length - top_edge;
178         if ((comp->posy != 0 && cutlen > 0.1) || comp->dy > 0.75*length) {
179           cutthick = comp->GetThickness() + 1.;
180           break;
181         } 
182       }
183       GeoShape* box1 = new GeoBox(cutthick/2., (longWidth+2.)/2., cutlen);
184       box1->ref();
185       strd = &(strd->subtract( (*box1) << HepTranslate3D( (totthick-cutthick)/2., 0., length/2.) ) );
186       box1->unref();
187     }
188   }
189 
190   // Skip mother volume modifications for assembly volumes since they cannot cause clash
191   if (!isAssembly) {
192 
193     bool testEIL = (stname == "EIL" && std::abs(zi) != 1
194                                     && (std::abs(zi) != 4 || fi == 0 || fi == 4));
195 
196     if ((m_enableFineClashFixing &&
197          (stname == "BML" || stname == "BIL" || stname == "BOL" ||
198           stname == "BMS" || stname == "BIS" || stname == "BOS")) ||
199         testEIL) {
200       double root3 = 1.7320508;
201       StandardComponent* comp = 0;
202       double mdt_half_thick = -1.;
203       double mdt_pos = 0.;
204       double xtube1 = 0;
205       double xtube2 = 0;
206       
207       int index = 0;
208       int mdt_index[4] = {0, 0, 0, 0};
209       for (int i = 0; i < station->GetNrOfComponents(); i++) {
210         comp = (StandardComponent*)station->GetComponent(i);
211         std::string compName = (comp->name).substr(0,3);
212         if (compName == "MDT") {
213           mdt_index[index] = i;
214           index += 1;
215         }
216       }
217  
218       // Prepare boxes and cylinders for chamber volume mods
219       GeoShape* box = new GeoBox((totthick+2.)/2., (longWidth+2.)/2., halfpitch);
220       box->ref();
221       const GeoShape* frontcyl = new GeoTube(0.0, halfpitch+0.001, longWidth/2.);
222       frontcyl = &( (*frontcyl) << HepRotateX3D(90.*deg) );
223       frontcyl->ref();
224       const GeoShape* backcyl = new GeoTube(0.0, halfpitch-0.001, (longWidth+2.)/2.);
225       backcyl = &( (*backcyl) << HepRotateX3D(90.*deg) );
226       backcyl->ref();
227 
228       if (index > 0) {
229         // If chamber has MDTs, shorten length by halfpitch (remove what was added in DBReader.h)
230         strd = &(strd->subtract( (*box) << HepTranslate3D(0., 0., length/2.) ) );
231         double sign = 1.;
232         for (int i = 0; i < index; i++) {
233           comp = (StandardComponent*)station->GetComponent(mdt_index[i]);
234           mdt_half_thick = comp->GetThickness()/2.;
235           mdt_pos = -totthick/2. + comp->posz + mdt_half_thick;
236           if (geometry_version.substr(0,1) != "P") mdt_pos += amdbOrigine_along_thickness;
237           xtube1 = sign*(mdt_half_thick - (root3 + 1.)*halfpitch);
238           xtube2 = sign*(mdt_half_thick - (3*root3 + 1.)*halfpitch);
239           strd = &(strd->add( (*frontcyl) << HepTranslate3D(mdt_pos+xtube1, 0., length/2.-halfpitch) ) );
240           strd = &(strd->subtract( (*backcyl) << HepTranslate3D(mdt_pos+xtube1, 0., -length/2.) ) );
241 
242           if (stname == "BIL" || (stname == "BIS" && std::abs(zi) != 8) || testEIL) {
243             strd = &(strd->add( (*frontcyl) << HepTranslate3D(mdt_pos+xtube2, 0., length/2.-halfpitch) ) );
244             strd = &(strd->subtract( (*backcyl) << HepTranslate3D(mdt_pos+xtube2, 0., -length/2.) ) );
245           }
246 
247           sign *= -1.;
248         }
249       }
250       if (stname != "EIL") {
251         if (zi < 0 && !is_mirrored) strd = &( (*strd) << HepRotateX3D(180.*deg) );
252       }
253 
254       box->unref();
255       frontcyl->unref();
256       backcyl->unref();
257     } // fine clash fixing
258   } // !isAssembly
259 
260 
261   // This will allow the MDT tube structure to be mirrored w.r.t. the chamber at z>0
262   // and to correctly place any other component in the station 
263   if (zi<0 && !is_mirrored && stName[0]=='B' && (geometry_version != "CTB2004") ) {
264     if (station->hasMdts()) {
265       amdbOrigine_along_length += halfpitch;
266     }
267   }
268 
269   if (m_verbose) log << MSG::VERBOSE <<"amdb origine: in the length direction = "
270                      << amdbOrigine_along_length<<" in the thickness direction = "
271                      << amdbOrigine_along_thickness << endreq;
272 
273   if (isAssembly) if (m_debug) log<<MSG::DEBUG<<"Station  "<<stName<<" at zi, fi "
274                                   <<zi<<" "<<fi+1<<" will be described as  Assembly"<<endreq;
275 
276   // for BOG in layout Q we will have to shorten CHV, CMI as these
277   //   are not shortened in AMDB
278   double lengthShiftCP = 0.;
279 
280   // if this is a BOG, we want to make cutouts in the MOTHER VOLUME
281   if (stName.substr(0,3) == "BOG" &&
282       (m_manager->IncludeCutoutsBogFlag() || m_manager->IncludeCutoutsFlag()))
283   {
284     if (m_verbose) log << MSG::VERBOSE << "amdb org: length= "
285                        << amdbOrigine_along_length << " thickness= "
286                        << amdbOrigine_along_thickness << endreq;
287       // std::cout<<"This is "<<stName<<" at zi/fi "<<zi<<"/"<<fi<<std::endl;
288     std::string statType=stName.substr(0,3);
289     if (station->GetNrOfCutouts() >0 ) {
290       if (m_debug) log << MSG::DEBUG << "Station  "<<stName<<" at zi, fi "<<zi
291                        <<" "<<fi+1<<" has components with cutouts " << endreq;
292       isAssembly = true;
293         // std::cout << "From the MuonChamber " << stName << " at zi, fi " << zi
294         //           << " " << fi+1 << " this will be an assembly " << std::endl;
295 
296       // look for FIRST component with cutouts and loop over all of the cutouts:
297       bool foundCutouts = false;
298       for (int j = 0; j < station->GetNrOfComponents(); j++) {
299         StandardComponent* c = (StandardComponent*)station->GetComponent(j);
300         // std::cout << "Loop over components " << j << " name " << c->name
301         //           << " Job = " << c->index << " foundCutouts = " << foundCutouts
302         //           << std::endl;
303         if (!foundCutouts) {
304           for (int ii=0; ii<station->GetNrOfCutouts();ii++) {
305             Cutout* cut = station->GetCutout(ii);
306             // if this is a BOG in layout Q, set the CP param:
307             //   (both cuts have same length so ok to reset it)
308             // std::cout<<"Loop over station cutouts "<<ii<<std::endl;
309             if (geometry_version.substr(0,1) != "P") {
310               lengthShiftCP = cut->lengthY;
311                             // also do here some tweaking to prevent undershoot
312                             //  of the cutouts wrt mother volume:
313                             if ( fabs(cut->dx-600.7)<0.1 ) 
314                             {
315                                 cut->dx      = cut->dx + 10.*mm;
316                                 cut->widthXs = cut->widthXs + 20.*mm;
317                                 cut->widthXl = cut->widthXl + 20.*mm;
318                                 //std::cout<<" redefining par.s for BOG1 cutouts "
319                                 //<<std::endl;
320                             }
321                             if ( fabs(cut->dx+600.7)<0.1 ) 
322                             {
323                                 cut->dx      = cut->dx - 10.*mm;
324                                 cut->widthXs = cut->widthXs + 20.*mm;
325                                 cut->widthXl = cut->widthXl + 20.*mm;
326                             }
327                             if (fabs(cut->lengthY-180.2)<0.001)
328                             {
329                                 cut->lengthY = cut->lengthY+(0.010)*mm;
330                                 //imt       std::cout<<"Redefining "<<stName<<" cut lengthY to "
331                                 //imt                <<cut->lengthY
332                                 //imt                <<std::endl;
333                             }
334                             if (fabs(cut->dy-1019.8)<0.001)
335                             {
336                                 cut->dy = 1216.4185-cut->lengthY;
337                             }
338             }
339             // create the cutout with the full thickness of the STATION
340             cut->setThickness(totthick*1.01);// extra to be sure
341             // std::cout << "cutout subtype/icut/ijob = " << cut->subtype << "/" << cut->icut
342             //           << "/" << cut->ijob << std::endl;
343             if ((cut->subtype ==
344                  mysql->allocPosFindSubtype(statType, fi, zi))&&
345                 (cut->icut == mysql->allocPosFindCutout(statType, fi, zi))&&
346                 (cut->ijob == c->index))
347             {
348               foundCutouts = true;
349             }
350           } // Loop over cutouts
351         } // If no cutouts
352       } // Loop over components
353     }
354   }// end of special loop just for cutouts
355 
356   // remove overlaps between end-cap and forward region of TGC stations,
357   // T[1-3]E1_station and T[1-3]F1_station
358   if (stName.substr(0,1) == "T" && stName.substr(2,1) == "E" && stName.substr(1,1) != "4") {
359     GeoTrd* strdoverlap = new GeoTrd(totthick/4, totthick/4, width/2, 
360                                      longWidth/2, 400./2);
361     strd = &(strd->subtract((*strdoverlap) << HepTranslate3D(-totthick/4., 0., -length/2+400./2.) ));
362   }
363     
364   const GeoMaterial* mtrd = 0;
365   if (useAssemblies || isAssembly) {
366     mtrd = matManager->getMaterial("special::Ether");
367   } else {
368     mtrd = matManager->getMaterial("std::Air");
369   }
370   GeoLogVol* ltrd = new GeoLogVol(stName+"_Station", strd, mtrd);
371   GeoPhysVol* ptrd = new GeoPhysVol(ltrd);
372  
373   double ypos;
374   double zpos;
375   double xpos;  //imt new
376   static double irad = 0;
377   int ndbz[2] = {0,0};
378 
379   // Compute how many RPC modules there are in the station 
380   int nDoubletR = 0;
381   int nRpc = 0;
382   int nTgc = 0;
383   int nCsc = 0;
384   int nMdt = 0;
385   double previous_depth = 0.;
386   if (m_verbose) log << MSG::VERBOSE << " Station Name = " << stName 
387                      << " fi/zi " << fi << "/" << zi
388                      <<" defining the n. of DoubletR to ";
389 
390   for (int j = 0; j < station->GetNrOfComponents(); j++) {
391     StandardComponent* d = (StandardComponent*)station->GetComponent(j);
392     std::string cn = (d->name).substr(0,3);
393     if (cn == "RPC") {
394       nRpc++;
395       if ( nRpc == 1 )  nDoubletR++;
396       double depth = -thickness/2.+d->posz+d->GetThickness()/2.;
397       // std::cerr << " nRpc, nDoubletR, depth " << nRpc << " " << nDoubletR 
398       //           << " " << depth;
399       if ( nDoubletR == 1 &&  nRpc>1 && depth*previous_depth < 0) nDoubletR++;
400       // std::cerr<<" updated to "<<nDoubletR<<std::endl;
401       previous_depth = depth;
402     }
403     if (cn == "CSC") {nCsc++;}
404     if (cn == "TGC") {nTgc++;}        
405     if (cn == "MDT") {nMdt++;}
406   }
407   if (m_debug){
408     log<<MSG::DEBUG<<" "<<nDoubletR;
409     log<<MSG::DEBUG<<" nMdt/Rpc/Tgc/Csc "<<nMdt<<"/"<<nRpc<<"/"<<nTgc<<"/"<<nCsc<<endreq;
410   }
411   //std::cerr<<" nRpc, nDoubletR "<<nRpc<<" "<<nDoubletR<<" in "<<stName<<std::endl; 
412    
413   // Get location and dimensions of long beams and pass them to cross beams
414   // in order to make holes
415   int numLB = -1;
416   double LBheight = 0;
417   double LBwidth = 0;
418   double LBpos[2] = {-1, -1};
419   for (int i = 0; i < station->GetNrOfComponents(); i++) {
420     StandardComponent* c = (StandardComponent*)station->GetComponent(i);
421     std::string cname = (c->name).substr(0,2);
422     if (cname == "LB") {
423       LBI* lb = (LBI*) mysql->GetTechnology(c->name);
424       numLB++;
425       LBpos[numLB] = c->posy + c->dy/2.;
426       LBheight = lb->height;
427       LBwidth = c->dy;
428     }
429     if (numLB > 0) break;   // only 2 LBs per chamber
430   }
431                                                                                                                          
432   for (int i = 0; i < station->GetNrOfComponents(); i++) {
433     StandardComponent* c = (StandardComponent*)station->GetComponent(i);
434     std::string cname = (c->name).substr(0,3);
435     if (cname == "CRO" || cname == "CMI" || cname == "CHV") {
436       CbmComponent* ccbm = (CbmComponent*)c;
437       ccbm->lb_height = LBheight;
438       ccbm->lb_width = LBwidth;
439       ccbm->hole_pos1 = LBpos[0];
440       ccbm->hole_pos2 = LBpos[1];
441     }
442   }
443     
444   // Look for the subtype of the CMI in the chamber to let LB know ...
445   std::string CMIcomponentNumber = "";
446   for (int j = 0; j < station->GetNrOfComponents(); j++) {
447     StandardComponent* d = (StandardComponent*)station->GetComponent(j);
448     std::string cn = (d->name).substr(0,3);
449     if (cn == "CMI") {
450       CMIcomponentNumber = (d->name).substr(3,2);
451       break;
452     }
453   }
454   for (int j = 0; j < station->GetNrOfComponents(); j++) {
455     StandardComponent* d = (StandardComponent*)station->GetComponent(j);
456     std::string cn = (d->name).substr(0,2);
457     if (cn == "LB") {
458       LbiComponent* lbic = (LbiComponent*)d;
459       if (lbic) {
460         // std::cerr << "associating to LB comp " << lbic->name << " CMIsubtype = "
461         //           << CMIcomponentNumber << std::endl;
462         lbic->associated_CMIsubtype = CMIcomponentNumber;
463       }            
464       else log << MSG::ERROR 
465                << "MuonChamber :: cannot associate a CMI subtype to the LB component "
466                << endreq;
467     }
468   }
469 
470   // Build the MuonStation(readout-geometry) corresponding to this MuonChamber(raw-geometry)
471   MuonStation* mstat;
472   if (stName.substr(0,1) == "B")
473     mstat = new MuonStation(stName.substr(0,3), width, totthick, length,
474                             longWidth, totthick, length, zi, fi+1,
475                             (zi<0 && !is_mirrored)); //!< fi here goes from 0 to 7; in amdb from 1 to 8;
476   else
477     mstat = new MuonStation(stName.substr(0,3), width, length, totthick,
478                             longWidth, length, totthick, zi, fi+1,
479                             (zi<0 && !is_mirrored));//!< fi here goes from 0 to 7; in amdb from 1 to 8;
480   m_manager->addMuonStation(mstat);
481   if (m_debug) log << MSG::DEBUG << " Building a MuonStation for this MuonChamber "
482                    << station->GetName() << " at zi, fi "
483                    << zi << " " << fi+1 << " is_mirrored " << is_mirrored << endreq;
484 
485 
486   // here the big loop over the components !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
487 
488   for (int i = 0; i < station->GetNrOfComponents(); i++) {
489     StandardComponent* c = (StandardComponent*)station->GetComponent(i);
490     if (m_verbose) log << MSG::VERBOSE 
491                 << " Component loop for " << stName << " " << stationType
492                 << " at zi, fi " << zi << " " << fi+1 << "  " << c->name
493                 << " thickness " << c->GetThickness() << " length " << c->dy
494                 << " w, lw " << c->dx1 << " " << c->dx2 << std::endl;
495 
496     ypos = -thickness/2. + c->posz + c->GetThickness()/2.;
497     zpos = 0.;
498     xpos = 0.;
499 
500     if (geometry_version.substr(0,1) != "P") {
501       ypos = -thickness/2. + (c->posz+amdbOrigine_along_thickness)+c->GetThickness()/2.;
502       zpos = -length/2. + amdbOrigine_along_length + c->posy + c->dy/2.;
503       xpos = c->posx;
504     }
505         
506     std::string techname = c->name;
507     std::string type = techname.substr(0,3);
508             
509     GeoVPhysVol* lv = NULL;
510     GeoVPhysVol* lvd = NULL;
511     GeoVPhysVol* lvs = NULL;
512     GeoVPhysVol* lvo = NULL;
513     GeoFullPhysVol* lvm = NULL;
514     GeoFullPhysVol* lvr = NULL;
515     GeoFullPhysVol* lvt = NULL;
516     GeoFullPhysVol* lvc = NULL;
517 
518     double BeamHeight;            
519 
520     // Are there cutouts?
521     std::string statType = stName.substr(0,3);
522     double cthickness = c->GetThickness();
523     int ncutouts = 0;
524     std::vector<Cutout*> vcutdef;
525     std::vector<Cutout*> vcutdef_todel;
526     for (int ii = 0; ii < station->GetNrOfCutouts(); ii++) {
527       Cutout* cut = station->GetCutout(ii);
528       cut->setThickness(cthickness*1.01); // extra thickness to be sure
529       if ((cut->subtype ==
530            mysql->allocPosFindSubtype(statType, fi, zi))&&
531           (cut->icut == mysql->allocPosFindCutout(statType, fi, zi))&&
532           (cut->ijob == c->index))
533       {
534         double tempdx = cut->dx;
535         double tempdy = cut->dy;
536         double templengthY = cut->lengthY;
537         cut->dx = 0.;
538         cut->dy = 0.;
539         if (geometry_version.substr(0,1) != "P" && stName.substr(0,3)=="BOG")
540         { // make the cutouts a bit longer
541           cut->lengthY=templengthY+31.;
542         }
543         cut->dx = tempdx;
544         cut->dy = tempdy;
545         cut->lengthY = templengthY;
546         // in thickness, cutout will coincide with component
547 // not needed (DHW)  double xposcut = 0.;  // rel. to component thickness
548 //        double yposcut = -xpos+cut->dx; // rel. to component width
549 //        double zposcut = -zpos+cut->dy; // rel. to component length
550 //        if (geometry_version.substr(0,1) != "P" && stName.substr(0,3)=="BOG")
551 //        {
552           // move the extended cut region out a little
553 //          if (cut->dy < 10.) zposcut = -zpos+cut->dy - 15.5;
554 //        }
555         ncutouts++;
556 
557         // Corrected cutout values for BMS7, BMS14
558         if (stName.substr(0,3) == "BMS") {
559           if (fi == 3) {
560             if (std::abs(zi) == 1) {
561               double margin = 1.0;  // make cutout a little bigger to avoid coincident boundaries
562               if (type == "RPC" || type == "DED") {
563                 cut->widthXl += 2*margin;
564                 cut->widthXs += 2*margin;
565                 cut->dx += margin;
566                 cut->lengthY += 2*margin;
567                 cut->dy = -margin;
568               }
569             }
570             if (zi == -1) {
571               if (type == "MDT") cut->dy = 0.;
572             }
573           }
574         }
575 
576         if (stName.substr(0,3) == "BOS" && zi == -6 && type == "MDT") {
577           cut->dy = c->dy - cut->dy - cut->lengthY - halfpitch;
578         }
579 
580         if (is_mirrored || (zi < 0 && type == "MDT") ) {
581           // MDT in chambers explicitly described at z<0 have to be 
582           // rotated by 180deg to adj. tube staggering
583           // reverse the position (x amdb) of the cutout if the station is mirrored
584           Cutout* cutmirr = new Cutout(*cut);
585           cutmirr->dx = - cutmirr->dx;
586           // this way, after the rotation by 180 deg, the cut will be at the same global phi
587           // it has for the station at z>0
588           vcutdef.push_back(cutmirr);
589           vcutdef_todel.push_back(cutmirr);
590 
591         } else if (stName.substr(0,3) == "BMS" && std::abs(zi) == 6) {
592           // BMS2, BMS13
593           Cutout* bms2cutfix = new Cutout(*cut);
594           bms2cutfix->dy = cut->dy - c->posy;
595           vcutdef.push_back(bms2cutfix);
596           vcutdef_todel.push_back(bms2cutfix);
597         } else if (stName.substr(0,3) == "BMS" && std::abs(zi) == 4) {
598           // BMS6, BMS11
599           Cutout* bms6cutfix = new Cutout(*cut);
600           bms6cutfix->dx = 0.;
601           bms6cutfix->dy = 0.;
602           if (cut->ijob < 28) {
603             bms6cutfix->dy = 15.;
604           } else if (cut->ijob == 33) {
605             bms6cutfix->dy = 10.;
606           }
607           if (zi == 4 && (cut->ijob == 21 || cut->ijob == 25) ) bms6cutfix->dy = c->dy - cut->lengthY;
608           if (zi == -4 && (cut->ijob == 29 || cut->ijob == 33) ) bms6cutfix->dy = c->dy - cut->lengthY;
609           vcutdef.push_back(bms6cutfix);
610           vcutdef_todel.push_back(bms6cutfix);
611         } else if (stName.substr(0,3) == "BMS" && std::abs(zi) == 2) {
612           // BMS5, BMS9
613           Cutout* bms5cutfix = new Cutout(*cut);
614           bms5cutfix->dx = 0.;
615           bms5cutfix->dy = 0.;
616           if (zi == 2 && (cut->ijob == 32 || cut->ijob == 36) ) bms5cutfix->dy = c->dy - cut->lengthY;
617           if (zi == -2 && (cut->ijob == 24 || cut->ijob == 28) ) bms5cutfix->dy = c->dy - cut->lengthY;
618           vcutdef.push_back(bms5cutfix);
619           vcutdef_todel.push_back(bms5cutfix);
620 
621         } else if (stName == "BOS5") {
622           // Looks like a problem in the database for BOS5.
623           // Hard-code the values until there is a fix.  DHW
624           Cutout* bos5cutfix = new Cutout(*cut);
625           if (type == "RPC") bos5cutfix->dy = 0.0;
626           if (type == "DED") bos5cutfix->dy = c->dy - cut->lengthY;
627           vcutdef.push_back(bos5cutfix);
628           vcutdef_todel.push_back(bos5cutfix);
629 
630 //        } else if (stName.substr(0,3) == "BMS" && zi == 3) {
631           // Looks like a problem in the database for BMS4 (cut->dy = -110.83)
632           // Hard-code the values until there is a fix.  DHW
633 //          if (type == "MDT") {
634 //            Cutout* bms4cutfix = new Cutout(*cut);
635 //            bms4cutfix->dy = 110.83;
636 //            vcutdef.push_back(bms4cutfix);
637 //            vcutdef_todel.push_back(bms4cutfix);
638 //            std::cout << " BMS4 cut fixed for component " << c->name << std::endl;
639 //          }
640    
641         } else if (type == "TGC") {
642           // In AMDB, y coordinates of cutout and component are given by
643           // radius from detector z-axis.  To get standard y value of cutout, 
644           // subtract radius of component from radius of cutout 
645           Cutout* tgccut = new Cutout(*cut);
646           tgccut->dy -= c->posy;  //
647           vcutdef.push_back(tgccut);
648           vcutdef_todel.push_back(tgccut);
649 
650         } else {
651           vcutdef.push_back(cut);
652         }
653       }
654     } // Loop over cutouts in station
655 
656     if (ncutouts > 0) if (m_debug) log << MSG::DEBUG 
657                           << c->name << " of station " 
658                           << stName << " at fi/zi " << fi+1 << "/" 
659                           << zi << " has " << ncutouts << " cutouts "
660                           << endreq;
661 
662     // define here the total transform that will be applied to component:
663     HepTransform3D htcomponent;
664     GeoTransform* xfcomponent = NULL;
665     GeoAlignableTransform * xfaligncomponent = NULL;
666 //     // for RPCs we need a vector of transforms for M28 geometry...
667 //     std::vector<GeoTransform*> xfrpccomponent;
668 
669     if (type == "CRO") {
670       if (stName.substr(0,1) != "B" && is_mirrored) mstat->setxAmdbCRO(-xpos);
671       else mstat->setxAmdbCRO(xpos);
672     }
673         
674     if (type == "MDT") {
675       htcomponent = HepTranslateX3D(ypos)*HepTranslateZ3D(zpos)*HepTranslateY3D(xpos);
676       if (zi < 0 && !is_mirrored && stName[0] == 'B'
677           && (geometry_version != "CTB2004") ) { 
678         // this (rotation +  shift of halfpitch) will mirror the tube structure w.r.t. the chamber at z>0
679          htcomponent = htcomponent*HepRotateX3D(180.*deg);
680          if (geometry_version.substr(0,3) != "P03" )
681                 htcomponent = htcomponent*HepTranslateZ3D(halfpitch);
682       }
683           
684       // ss - 24-05-2006 I don't really understand if this is needed at all
685       //      it was introduced by Isabel T.
686       if (zi < 0 && stName.substr(0,3) == "BOG" && is_mirrored) {
687         //            htcomponent = htcomponent*HepRotateX3D(180.*deg);
688         //      tubes OK but chambers wrong
689         //            htcomponent = HepRotateX3D(180.*deg)*htcomponent;
690         //      chambers OK but tubes wrong
691         htcomponent = HepRotateX3D(180.*deg)*htcomponent*
692                       HepRotateX3D(180.*deg);  // turn chambers but go back for tubes
693       } // ss - 24-05-2006 I don't really understand if this is needed at all
694           
695       xfaligncomponent = new GeoAlignableTransform(htcomponent);
696       std::string key=stName+techname;
697 
698       // for cutouts:
699       // MDT cutouts for BOS1,5, BMS7,14, (problem with BMS4,10),  EMS
700       bool mdtCutoutFlag = ((stname == "BOS" && std::abs(zi) == 6) ||
701                             (stname == "BMS" && (std::abs(zi) == 1 && fi == 3)) ||
702                             (stname == "EMS" && (std::abs(zi) == 1 || std::abs(zi) == 3)));
703       if (((m_manager->IncludeCutoutsFlag() &&  mdtCutoutFlag) || 
704            (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG") ) 
705           && zi >= 0)
706         key += "p"+buildString(mysql->allocPosFindSubtype(statType, fi, zi),0)
707                +"_"+buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
708       else if (((m_manager->IncludeCutoutsFlag() && mdtCutoutFlag) ||
709                 (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG") ) 
710           && zi < 0)
711         key += "m"+buildString(mysql->allocPosFindSubtype(statType, fi, zi),0)
712                +"_"+buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
713 
714       FPVMAP* savemem = FPVMAP::GetPointer();
715       GeoVPhysVol* fpv = savemem->GetDetector(key);
716       if (fpv == 0) {
717         Mdt* r = new Mdt(c, stName+techname);
718         if (m_debug) log << MSG::DEBUG << " Building an MDT for station "
719                          << key << " component name is " << c->name 
720                          << " m_manager->IncludeCutoutsFlag() "
721                          << m_manager->IncludeCutoutsFlag() 
722                          << " m_manager->IncludeCutoutsBogFlag() "
723                          << m_manager->IncludeCutoutsBogFlag() << endreq;
724         if ((m_manager->IncludeCutoutsFlag() && mdtCutoutFlag) ||
725             (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG"))
726         {
727           // std::cout << "Building the Mdt " << techname << " in station "
728           //           << stName << " at fi/zi " << fi << "/" << zi << std::endl;
729           lvm = r->build(vcutdef);
730         } else {
731           lvm = r->build();
732         }
733         //log<<MSG::DEBUG<<" Storing in FPVMAP with key "<<key<<endreq;
734         savemem->StoreDetector(lvm, key);
735         delete r;
736         r = 0;
737 
738       } else {
739         GeoFullPhysVol* rfpv = (GeoFullPhysVol*)fpv;
740         if (m_verbose) log << MSG::VERBOSE << " This MDT for station " 
741                            << key << " component name is "
742                            << c->name << " already exists; clone it " << endreq;
743         lvm = rfpv->clone();
744       }
745 
746     } else if (type=="SPA" && m_manager->MinimalGeoFlag() == 0) {
747       if (techname == "SPA01" && stName.substr(0,1) == "C") {
748         if (m_debug) log << MSG::DEBUG 
749                          << "Ficticious spacer SPA01 in CSC chamber - skip it "
750                          << endreq;
751         // ignore SPA 1 component of CSS/CSL chambers in R02.03 (it is there only for AMDB convenience,
752         // leaving the CSC envelop => global position of the station unchanged)
753         continue;
754       }
755 
756       htcomponent = HepTranslateX3D(ypos)*HepTranslateZ3D(zpos);
757       xfcomponent = new GeoTransform(htcomponent);
758       std::string key = stName+techname;
759       if ((m_manager->IncludeCutoutsFlag()||
760           (m_manager->IncludeCutoutsBogFlag()&&stName.substr(0,3) == "BOG")) && zi >= 0)
761         key += "p"+buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
762                "_"+buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
763       else if ((m_manager->IncludeCutoutsFlag() ||
764                (m_manager->IncludeCutoutsBogFlag()&&stName.substr(0,3)=="BOG")) && zi < 0)
765         key += "m"+buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
766                "_"+buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
767       FPVMAP* savemem = FPVMAP::GetPointer();
768       GeoVPhysVol *fpv = savemem->GetDetector(key);
769       if (fpv == 0) {
770         Spacer* r = new Spacer(c);
771         // log << MSG::DEBUG << " Building a SPA for station "
772         //     << key << " component name is " << c->name << endreq;
773         if (m_manager->IncludeCutoutsFlag()||
774             (m_manager->IncludeCutoutsBogFlag()&&stName.substr(0,3)=="BOG"))
775         {
776           lv = r->build(1);
777         } else {
778           lv = r->build();
779         }
780         // log << MSG::DEBUG << " Storing in FPVMAP with key " << key << endreq;
781         savemem->StoreDetector(lv, key);
782         delete r;
783         r = 0;
784       }
785       else lv = fpv;
786 
787     } else if ((type=="CHV" || type=="CRO" || type=="CMI" || 
788                 type=="LB0" || type == "LBI") && m_manager->MinimalGeoFlag() == 0) {
789       SpacerBeam* r = new SpacerBeam(c);
790       BeamHeight = r->height;
791       ypos = c->posx; 
792       double zpos1 = c->posy - length/2. + c->dy/2.;
793       if (geometry_version.substr(0,1) == "P") zpos = zpos1;
794       double xpos = (c->posz+amdbOrigine_along_thickness) - thickness/2. + BeamHeight/2.;
795       double angle = 0.;
796       if (fabs(c->excent) > 0.001) {
797         angle = atan((longWidth-width)/length/2.);
798         if (c->excent <0.) angle = -angle;
799       }
800 
801       // This is an attempt to provide some info to LB construction in order 
802       // to avoid the clash of LB with CXx in the endcaps ... 
803       if (type == "LB0") {
804         if (stName == "EML1" || stName == "EML6") {                     
805           if ((c->dx1 > width)  && zpos < 0.) {
806             r->width = 0.98*width;
807           }
808           if ((c->dx1/longWidth) > 0.98 && zpos > 0.) {
809             double mywidth = 0.93*longWidth;
810             r->width = mywidth;
811           }
812         }
813       }
814 //
815       if (type == "CMI" || type == "CHV" || type == "CRO") {
816         // Shorten CHV, CMI lengths to fit in BOL4 envelope
817         if (stname == "BOL" && zi == 1 && (fi+1) == 3) {
818           r->length = length - halfpitch;
819           zpos = -halfpitch/2.;
820         }
821       }
822 //
823       if (!is_mirrored) {
824         htcomponent = HepTranslate3D(xpos,ypos,zpos)*HepRotateX3D(angle);
825       } else {
826         htcomponent = HepTranslate3D(xpos,-ypos,zpos)*HepRotateX3D(-angle);
827       }
828       xfcomponent = new GeoTransform(htcomponent);
829       std::string key = stName+techname;
830       if ((m_manager->IncludeCutoutsFlag() ||
831           (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG")) 
832          && zi >= 0)
833         key += "p" + buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
834                "_" + buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
835       else if ((m_manager->IncludeCutoutsFlag() ||
836                (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG")) 
837               && zi < 0)
838         key += "m" + buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
839                "_" + buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
840 
841       // can have LB of different length in same station:
842       if (type.substr(0,2) == "LB") key += buildString(int(c->dx1),0);
843 
844       // log << MSG::DEBUG << " Building a SpacerBeam for station "
845       //                   << key << " component name is "
846       //                   << c->name << endreq;
847       FPVMAP* savemem = FPVMAP::GetPointer();
848       GeoVPhysVol* fpv = savemem->GetDetector(key);
849       if (fpv == 0 || (stName.substr(0,3) == "BOG" && type == "CMI")) {
850         if (stName.substr(0,3)=="BOG")
851           if (m_verbose) log << MSG::VERBOSE << " Building a SpacerBeam for station "
852                              << key << " component name is " << c->name << endreq;
853         if (m_manager->IncludeCutoutsFlag() ||
854             (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG"))
855         {
856           lvo = r->build(1, is_barrel);
857         } else {
858           lvo = r->build(is_barrel);
859         }
860           // log << MSG::DEBUG << "LB: " << r->name << " height is " <<
861           //     r->height << " length is " << r->length << " width is "
862           //                          << r->width << endreq;
863           // log << MSG::DEBUG << " Storing in FPVMAP with key " << key << endreq;
864         savemem->StoreDetector(lvo, key);
865           // AMDB origin is in bottom centre of bottom cross-piece at
866           // end of bar.
867           // From centre, it is -height/2 in x, 0 in y, -length/2 in z
868 
869       } else {
870         if (stName.substr(0,3)=="BOG") 
871           if (m_verbose) log << MSG::VERBOSE << " This spacerbeam for station "
872                              << key << " component name is "
873                              << c->name << " already exists; re-use it " << endreq;
874         lvo = fpv;
875       }
876       delete r;
877       r = 0;
878 
879     } else if (type == "RPC") {
880       // position stuff needed for cutout, used to be below:
881       RpcComponent* rp = (RpcComponent*)c;
882       int ndivy = rp->ndivy;
883       int ndivz = rp->ndivz;
884 //       double rwidth = width/ndivy;
885 //       double rlength = length/ndivz;
886 //       if (geometry_version == "M28") {
887 //         double zposi = -(ndivz-1)*rlength/2.;
888 //         for (int j = 0; j < ndivz; j++) {
889 //           double yposi = (ndivy-1)*rwidth/2.;
890 //           for (int i = 0; i < ndivy; i++) {
891 //             htcomponent = HepTranslateX3D(ypos )*HepTranslateY3D(yposi)*
892 //                           HepTranslateZ3D(zposi);
893 //             xfcomponent = new GeoTransform(htcomponent);
894 //             //xfrpccomponent.push_back(xfcomponent);
895 //             yposi -= rwidth;
896 //           }
897 //           zposi += rlength;
898 //         }
899 //      } else 
900 //      {
901         if (ndivz != 1 || ndivy != 1) log << MSG::ERROR << " RPC segmentation z,y "
902                                           << ndivz << " " << ndivy << std::endl;
903         double xpos = c->posx;
904         double zpos1 = -length/2. + c->posy+c->dy/2.;
905         if (geometry_version.substr(0,1) == "P") zpos = zpos1; // Preserve layout P03
906         // implement really the mirror symmetry
907         if (is_mirrored) xpos = -xpos;
908 
909         if (m_verbose) log << MSG::VERBOSE << " In station " << stName 
910                            << " with " << nDoubletR << " doubletR," 
911                            << " RPC " << (c->name).substr(3,2)
912                            << " has swap flag = " << rp->iswap
913                            << " ypos, zpos "
914                            << ypos << " " << zpos << " " << endreq;
915 
916         htcomponent = HepTranslateX3D(ypos)*
917                       HepTranslateY3D(xpos)*HepTranslateZ3D(zpos);
918         if (rp->iswap == -1) // this is like amdb iswap 
919         {
920           htcomponent = htcomponent*HepRotateY3D(180*deg);
921         }
922         xfaligncomponent = new GeoAlignableTransform(htcomponent);
923         //xfrpccomponent.push_back(xfcomponent);
924         //      }
925 
926       // end of position stuff
927 
928       bool rpcCutoutFlag = (stname == "BOS" && std::abs(zi) == 6) ||
929                            (stname == "BMS" && (std::abs(zi) == 2 || std::abs(zi) == 4 || std::abs(zi) == 6) ) ||
930                            (stname == "BMS" && std::abs(zi) == 1 && fi == 3);
931       std::string key=stName+techname;
932       if (((m_manager->IncludeCutoutsFlag() && rpcCutoutFlag) ||
933           (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG")) 
934          && zi >= 0) {
935         key += "p"+buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
936                 "_"+buildString(mysql->allocPosFindCutout(statType, fi, zi),0) +
937                 "_"+buildString(vcutdef.size(),0) +
938                 "_"+buildString(rp->iswap,0);
939       } else if (((m_manager->IncludeCutoutsFlag() && rpcCutoutFlag) ||
940                  (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG")) 
941                 && zi < 0) {
942         key += "m"+buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
943                 "_"+buildString(mysql->allocPosFindCutout(statType, fi, zi),0) +
944                 "_"+buildString(vcutdef.size(),0) +
945                 "_"+buildString(rp->iswap,0);
946       }
947       FPVMAP* savemem = FPVMAP::GetPointer();
948       GeoVPhysVol* fpv = savemem->GetDetector(key);
949       if (fpv == 0) {
950         Rpc* r = new Rpc(c);
951         r->setLogVolName(stName+techname);
952         //   log << MSG::DEBUG << " Building a RPC for station "
953         //       << key << " component name is "
954         //       << c->name << endreq;
955         if ((m_manager->IncludeCutoutsFlag() && rpcCutoutFlag) ||
956             (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG"))
957         {
958           lvr = r->build(m_manager->MinimalGeoFlag(), 1, vcutdef);
959         } else {
960           lvr = r->build(m_manager->MinimalGeoFlag());
961         }
962         // log<<MSG::DEBUG<<" Storing in FPVMAP with key "<<key<<endreq;
963         savemem->StoreDetector(lvr, key);
964         delete r;
965         r = 0;
966 
967       } else {
968         GeoFullPhysVol* rfpv = (GeoFullPhysVol*)fpv;
969         //log<<MSG::DEBUG<<" This RPC for station "<<key
970         //   <<" component name is "
971         //   <<c->name<<" already exists; clone it "<<endreq;
972         lvr = rfpv->clone();
973       }
974 
975     } else if (type=="DED" && m_manager->MinimalGeoFlag() == 0) {
976       double xpos = c->posx;
977       if (is_mirrored) xpos = -xpos;
978       double zpos1 = -length/2.+c->posy+c->dy/2.;
979       if (geometry_version.substr(0,1) == "P") zpos = zpos1; // Preserve layout P03
980       htcomponent = HepTranslateX3D(ypos)*HepTranslateY3D(xpos)*HepTranslateZ3D(zpos);
981       if (stname == "BMS" && (zi == -2 || zi == -4) && c->name == "DED03") 
982          htcomponent = htcomponent*HepRotateY3D(180*deg);
983       xfcomponent = new GeoTransform(htcomponent);
984 
985       bool dedCutoutFlag = (stname == "BOS" && std::abs(zi) == 6) ||
986                            (stname == "BMS" && (std::abs(zi) == 2 || std::abs(zi) == 4 || std::abs(zi) == 6) ) ||
987                            (stname == "BMS" && std::abs(zi) == 1 && fi == 3);
988       std::string key=stName+techname;
989       if (((m_manager->IncludeCutoutsFlag() && dedCutoutFlag) ||
990           (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG")) && zi>=0) {
991         key += "p"+buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
992                "_"+buildString(mysql->allocPosFindCutout(statType, fi, zi),0) +
993                "_"+buildString(vcutdef.size(),0);
994       }
995       else if (((m_manager->IncludeCutoutsFlag() && dedCutoutFlag) ||
996                (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG")) && zi<0) {
997         key += "m"+buildString(mysql->allocPosFindSubtype(statType, fi, zi),0)+
998                "_"+buildString(mysql->allocPosFindCutout(statType, fi, zi),0)+
999                "_"+buildString(vcutdef.size(),0);
1000       }
1001       key += buildString(int(c->dy),0) + "_" + buildString(int(c->dx1),0);
1002       FPVMAP* savemem = FPVMAP::GetPointer();
1003       GeoVPhysVol* fpv = savemem->GetDetector(key);
1004 
1005       if (fpv == 0) {
1006         Ded* r = new Ded(c);
1007         // log<<MSG::DEBUG<<" Building a DED for station "<<key
1008         // <<" component name is " <<c->name<<endreq;
1009         if ((m_manager->IncludeCutoutsFlag() && dedCutoutFlag) ||
1010             (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3) == "BOG"))
1011         {
1012           lvd = r->build(1, vcutdef);
1013         } else {
1014           lvd = r->build();
1015         }
1016           //   log<<MSG::DEBUG<<" Storing in FPVMAP with key "
1017           //   <<key<<endreq;
1018         savemem->StoreDetector(lvd, key);
1019         delete r;
1020         r = 0;
1021 
1022       } else {
1023         lvd = fpv;
1024       }
1025                 
1026     } else if (type=="SUP" && m_manager->MinimalGeoFlag() == 0) {
1027         ypos = -thickness/2. + c->posz;
1028         SupComponent* csup = (SupComponent*)c;
1029         double zpos = -length/2. + c->posy+c->dy/2. - csup->zAMDB0();
1030         ypos = ypos - csup->xAMDB0();
1031         double xpos = c->posx - csup->yAMDB0();
1032         //            log<<MSG::DEBUG
1033         //               <<" show AMDB origin with respect to phys vol centre: "
1034         //               <<csup->xAMDB0()<<" "
1035         //               <<csup->yAMDB0()<<" "
1036         //               <<csup->zAMDB0()<<endreq;
1037         //            log<<MSG::DEBUG<<" z transform done"<<endreq;
1038         //            log<<MSG::DEBUG<<" ypos = "<<ypos<<endreq;
1039         //            log<<MSG::DEBUG<<" y transform done"<<endreq;
1040         //            log<<MSG::DEBUG<<" x transform done"<<endreq;
1041         //            log<<MSG::DEBUG<<" its centre x-translated by "<<ypos;
1042         //            log<<" y-translated by "<<xpos;
1043         //            log<<" z-translated by "<<zpos<<endreq;
1044         htcomponent = HepTranslateX3D(ypos)*HepTranslateY3D(xpos)*
1045                       HepTranslateZ3D(zpos);
1046         std::string key = stName+techname;
1047         if ((m_manager->IncludeCutoutsFlag() ||
1048             (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3)=="BOG")) 
1049             && zi >= 0)
1050           key += "p"+buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
1051                  "_"+buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
1052         else if ((m_manager->IncludeCutoutsFlag()||
1053                  (m_manager->IncludeCutoutsBogFlag() && stName.substr(0,3)=="BOG")) 
1054                  && zi < 0)
1055           key += "m"+buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
1056                  "_"+buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
1057         FPVMAP* savemem = FPVMAP::GetPointer();
1058         GeoVPhysVol* fpv = savemem->GetDetector(key);
1059         if (fpv == 0) {
1060           // log<<MSG::DEBUG<<" definig ypos, from thickness & c->posz = "
1061           // <<-thickness/2.<<" "<<c->posz<<endreq;
1062           //                 Sup *r=new Sup(c);
1063           //                 lvs=r->build();
1064           //   log<<MSG::DEBUG<<" a pointer to a sup " <<lvs
1065           // <<" is now available in the station "<<endreq;
1066           // log<<MSG::DEBUG<<" Storing in FPVMAP with key "<<key<<endreq;
1067           savemem->StoreDetector(lvs, key);
1068         } else {
1069           lvs = fpv;
1070         }
1071 
1072     } else if (type == "TGC") {
1073       TgcComponent* tg = (TgcComponent*)station->GetComponent(i);
1074       TgcComponent* tgInner = (TgcComponent*)station->GetComponent(0);
1075       irad = tgInner->posy;
1076       TgcComponent* tgOuter = 
1077               (TgcComponent*)station->GetComponent(station->GetNrOfComponents()-1);
1078       double orad = tgOuter->posy + tgOuter->dy;
1079       double start = -(orad-irad)/2. + (tg->posy-irad) + tg->dy/2;
1080       double xstart = -thickness/2. + tg->GetThickness()/2.;
1081       htcomponent = HepTranslateX3D(xstart + tg->posz)*HepTranslateZ3D(start);
1082       xfaligncomponent = new GeoAlignableTransform(htcomponent);
1083 
1084       // Define key for this TGC component
1085       std::string key = stName + techname;
1086       if (m_manager->IncludeCutoutsFlag()) {
1087         if (mysql->allocPosFindCutout(statType, fi, zi) > 0) {
1088           // If there is a cutout for this chamber, give it a special key
1089           if (zi >= 0)
1090             key += "p" + buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
1091                    "_" + buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
1092           else if (zi < 0)
1093             key += "m" + buildString(mysql->allocPosFindSubtype(statType, fi, zi),0) +
1094                    "_" + buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
1095         }
1096       }
1097       char chswidth[32];
1098       sprintf(chswidth,"%i",int(10*c->dx1));
1099       key += chswidth;
1100 
1101       FPVMAP* savemem = FPVMAP::GetPointer();
1102       GeoVPhysVol* fpv = savemem->GetDetector(key);
1103       if (fpv == 0) {
1104         Tgc* t = new Tgc(c);
1105         t->setLogVolName(stName+techname);
1106         if (m_manager->IncludeCutoutsFlag()) {
1107           lvt = t->build(m_manager->MinimalGeoFlag(), 1, vcutdef);
1108         } else {
1109           lvt = t->build(m_manager->MinimalGeoFlag());
1110         }
1111         savemem->StoreDetector(lvt, key);
1112         delete t;
1113         t = 0;
1114       } else {
1115         GeoFullPhysVol* rfpv = (GeoFullPhysVol*)fpv;
1116         lvt = rfpv->clone();
1117       }
1118 
1119     } else if (type=="CSC") {
1120       htcomponent = HepTranslateX3D(ypos)*HepTranslateZ3D(zpos);
1121       xfaligncomponent = new GeoAlignableTransform(htcomponent);
1122       // Here define the key for this CSC component
1123       std::string key = stName+techname;
1124       if (m_manager->IncludeCutoutsFlag()
1125          && zi >= 0)
1126         key += "p" + buildString(mysql->allocPosFindSubtype(statType, fi, zi),0)+
1127                "_" + buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
1128       else if (m_manager->IncludeCutoutsFlag()
1129          && zi < 0)
1130         key += "m" + buildString(mysql->allocPosFindSubtype(statType, fi, zi),0)+
1131                "_" + buildString(mysql->allocPosFindCutout(statType, fi, zi),0);
1132       FPVMAP* savemem = FPVMAP::GetPointer();
1133 
1134       GeoVPhysVol* fpv = savemem->GetDetector(key);
1135       if (fpv == 0) {
1136         Csc* t = new Csc(c);
1137         t->setLogVolName(stName+techname);
1138           // log<<MSG::DEBUG<<" Building a CSC for  station "
1139           // <<key<<" component name is "<<c->name<<endreq;
1140         if (m_manager->IncludeCutoutsFlag() ) {
1141           lvc = t->build(m_manager->MinimalGeoFlag(), 1, vcutdef);
1142         } else {
1143           lvc = t->build(m_manager->MinimalGeoFlag());
1144         }
1145         // log<<MSG::DEBUG<<" Storing in FPVMAP with key "<<key<<endreq;
1146         savemem->StoreDetector(lvc, key);
1147         delete t;
1148         t = 0;
1149       } else {
1150         GeoFullPhysVol* rfpv = (GeoFullPhysVol*)fpv;
1151         // log<<MSG::DEBUG<<" This CSC for station "<<key
1152         // <<" component name is "
1153         // <<c->name<<" already exists; clone it "<<endreq;
1154         lvc = rfpv->clone();
1155       }
1156 
1157     } else {
1158       if (type != "MDT" && type != "RPC" && type != "TGC" && type != "SUP"
1159                         && type != "DED" && type != "SPA" && type != "CHV" 
1160                         && type != "CRO" && type != "CMI" && type != "LB0" 
1161                         && type != "LBI") log << MSG::INFO << "Unknown component " 
1162                                               << type << endreq;
1163     }
1164 
1165     // Place components in chamber envelope
1166     if (lvm) {
1167       int stationEta = zi;
1168       int stationPhi = fi+1;
1169       int ml = 1;
1170       int tubel = 1;
1171       int tube = 1;
1172       if (ypos > 0.) ml = 2;
1173       std::string stag = "ml["+MuonGM::buildString(ml,0)+"]"+techname+"component";
1174       GeoNameTag* nm = new GeoNameTag(stag);
1175       ptrd->add(new GeoIdentifierTag(c->index));
1176       ptrd->add(nm);
1177 /*
1178         std::cout << " MDT position " <<
1179              (xfcomponent->getTransform())[0][0] << " " <<
1180              (xfcomponent->getTransform())[0][1] << " " <<
1181              (xfcomponent->getTransform())[0][2] << " " <<
1182              (xfcomponent->getTransform())[0][3] << " " << std::endl <<
1183              (xfcomponent->getTransform())[1][0] << " " <<
1184              (xfcomponent->getTransform())[1][1] << " " <<
1185              (xfcomponent->getTransform())[1][2] << " " <<
1186              (xfcomponent->getTransform())[1][3] << " " << std::endl <<
1187              (xfcomponent->getTransform())[2][0] << " " <<
1188              (xfcomponent->getTransform())[2][1] << " " <<
1189              (xfcomponent->getTransform())[2][2] << " " <<
1190              (xfcomponent->getTransform())[2][3] << " " << std::endl;
1191 */
1192       xfaligncomponent->setDelta(HepTransform3D::Identity);
1193       //delete xfcomponent;
1194       ptrd->add(xfaligncomponent);
1195       ptrd->add(lvm);
1196       const MdtIdHelper* mdt_id = m_manager->mdtIdHelper();
1197       MdtReadoutElement* det = new MdtReadoutElement(lvm, stName, zi, fi+1, 
1198                                                      is_mirrored, m_manager);
1199       Position ip = mysql->GetStationPosition(stName.substr(0,3),fi,zi);
1200       setMdtReadoutGeom(det, (MdtComponent*)c, ip);
1201       det->setHasCutouts(ncutouts > 0);
1202       det->setNofREinStation(nMdt, nRpc, nTgc, nCsc);
1203       det->setStationEta(stationEta);
1204       det->setStationPhi(stationPhi);
1205       det->setMultilayer(ml);
1206       det->setParentStationPV(PVConstLink(ptrd));
1207       det->setParentMuonStation(mstat);
1208       int jobIndex = c->index;
1209       mstat->addMuonReadoutElement(det,jobIndex);
1210       if (m_debug) log << MSG::DEBUG << std::string(stName+techname)
1211                        << " trying to build a MDT Id from stType/eta/phi/ml/tl/t "
1212                        << stationType << "/" << stationEta << "/"
1213                        << stationPhi << "/" << ml << "/" << tubel << "/" 
1214                        << tube << "\n Copy number is " << c->index 
1215                        << " tagName " << stag << endreq;
1216       Identifier id = mdt_id->channelID(stationType, stationEta,
1217                                         stationPhi, ml, tubel, tube);
1218       det->setIdentifier(id);
1219       det->setLastInitField(5);
1220         //=========================
1221         // A little debug section
1222 
1223         //    std::cout << "ID = " << mdt_id->show_to_string(id) << std::endl;
1224         //    std::cout << " Mdtreadoutelement normal = "  << std::endl;
1225         //    HepVector3D dumv=det->normal();
1226         //    std::cout << "(" << dumv.x() << ", " << dumv.y() << ", " << dumv.z()
1227         //              << ")" << std::endl;
1228         //    std::cout << " Mdtreadoutelement transform = "  << std::endl;
1229         //    HepTransform3D dummy=det->transform(id);
1230         //    std::cout << dummy[0][0] << " " << dummy[0][1] << " "
1231         //              << dummy[0][2] << " " << dummy[0][3] << std::endl
1232         //              << dummy[1][0] << " " << dummy[1][1] << " "
1233         //              << dummy[1][2] << " " << dummy[1][3] << std::endl
1234         //              << dummy[2][0] << " " << dummy[2][1] << " "
1235         //              << dummy[2][2] << " " << dummy[2][3] << std::endl;
1236         //=========================
1237       m_manager->addMdtReadoutElement(det, id);
1238     }
1239 
1240       if (lvc) {
1241         CscComponent* cs = (CscComponent*)station->GetComponent(i);
1242         int stationEta = zi;
1243         int stationPhi = fi+1;
1244         int chamberLayer = 1;
1245         if (ypos > 0.) chamberLayer = 2;
1246         std::string stag = "cl["+MuonGM::buildString(chamberLayer,0)+"]"+techname+"component";
1247         GeoNameTag   *nm = new GeoNameTag(stag);
1248         ptrd->add(new GeoIdentifierTag(c->index));
1249         ptrd->add(nm);
1250 /*
1251         std::cout << " CSC position " <<
1252                (xfcomponent->getTransform())[0][0] << " " <<
1253                (xfcomponent->getTransform())[0][1] << " " <<
1254                (xfcomponent->getTransform())[0][2] << " " <<
1255                (xfcomponent->getTransform())[0][3] << " " << std::endl <<
1256                (xfcomponent->getTransform())[1][0] << " " <<
1257                (xfcomponent->getTransform())[1][1] << " " <<
1258                (xfcomponent->getTransform())[1][2] << " " <<
1259                (xfcomponent->getTransform())[1][3] << " " << std::endl <<
1260                (xfcomponent->getTransform())[2][0] << " " <<
1261                (xfcomponent->getTransform())[2][1] << " " <<
1262                (xfcomponent->getTransform())[2][2] << " " <<
1263                (xfcomponent->getTransform())[2][3] << " " << std::endl;
1264 */
1265         xfaligncomponent->setDelta(HepTransform3D::Identity);
1266         //delete xfcomponent;
1267         ptrd->add(xfaligncomponent);
1268         ptrd->add(lvc);
1269 
1270         CscReadoutElement* det =
1271             new CscReadoutElement(lvc, stName, zi, fi+1, is_mirrored, m_manager);
1272         Position ip = mysql->GetStationPosition(stName.substr(0,3),fi,zi); 
1273         setCscReadoutGeom(det, cs, ip, geometry_version, stName);
1274 
1275         const CscIdHelper* csc_id = m_manager->cscIdHelper();
1276         det->setHasCutouts(ncutouts > 0);
1277         det->setNofREinStation(nMdt, nRpc, nTgc, nCsc);
1278         det->setStationEta(stationEta);
1279         det->setStationPhi(stationPhi);
1280         det->setChamberLayer(chamberLayer);
1281         det->setParentStationPV(PVConstLink(ptrd));
1282         det->setParentMuonStation(mstat);
1283         int jobIndex = c->index;
1284         mstat->addMuonReadoutElement(det,jobIndex);
1285         if (m_debug) log<<MSG::DEBUG<<std::string(stName+techname)
1286                         <<" trying to build a CSC Id from stType/eta/phi/ml "
1287                         <<stationType<<"/"
1288                         <<stationEta<<"/"
1289                         <<stationPhi<<"/"
1290                         <<chamberLayer<<"/ and /1/0/1  \n  Copy number is "<<c->index<<" tagName "
1291                         <<stag<<endreq;
1292         Identifier id = csc_id->channelID(stationType,
1293                                           stationEta,
1294                                           stationPhi,
1295                                           chamberLayer,
1296                                           1, 0, 1);
1297         det->setIdentifier(id);
1298         det->setLastInitField(5);
1299         m_manager->addCscReadoutElement(det, id);
1300       }
1301 
1302       if (lvt) {
1303         if (m_debug) log << MSG::DEBUG
1304                          << " Adding a TGC chamber to the tree zi,fi, is_mirrored "
1305                          << zi << " " << fi+1 << " " << is_mirrored << endreq;
1306 
1307         TgcComponent* tg = (TgcComponent*)station->GetComponent(i);
1308         if (m_verbose) log << MSG::VERBOSE << "There's a TGC named " << techname
1309                            << " of thickness " << tg->GetThickness() << endreq;
1310 
1311         const TgcIdHelper* tgc_id = m_manager->tgcIdHelper();
1312         int stationEta = 0;
1313         stationEta = tg->index;
1314         if (zi<0) stationEta = -stationEta;
1315         int nch = 0;
1316         int fioff = 0;
1317         int stationPhi = 0;
1318         if (geometry_version.substr(0,1) == "P" || geometry_version.substr(0,3) == "CTB") 
1319         {
1320           nch = 3;
1321           if ( (stName).substr(2,1) == "E"  &&
1322                (stName).substr(1,1) != "4" ) nch = 6;
1323           fioff = abs(zi);
1324           if (fioff>3 && (stName).substr(2,1) == "F")  fioff = fioff-3;
1325           stationPhi = fi*nch + fioff;
1326         } else 
1327         {
1328             stationPhi = MuonGM::stationPhiTGC(stName,fi+1,zi, geometry_version);
1329         }
1330         int ttag = 1000*stationPhi+tg->index;
1331         std::string stag = "stPhiJob["+MuonGM::buildString(ttag,0)
1332                             +"]"+techname+"tgccomponent";
1333         GeoNameTag* nm = new GeoNameTag(stag);
1334         int geoid = 0;
1335         if (useAssemblies || isAssembly) {
1336           geoid = c->index;
1337         } else {                
1338           if (zi < 0) ttag = -ttag;
1339             geoid = ttag;
1340         }
1341         ptrd->add(new GeoIdentifierTag(geoid));
1342         ptrd->add(nm);
1343         xfaligncomponent->setDelta(HepTransform3D::Identity);
1344         //delete xfcomponent;
1345         ptrd->add(xfaligncomponent);
1346         ptrd->add(lvt);
1347 
1348         TgcReadoutElement* det = new TgcReadoutElement(lvt, stName, zi, fi+1,
1349                                                        is_mirrored, m_manager);
1350         Position ip = mysql->GetStationPosition(stName.substr(0,3),fi,zi);
1351         setTgcReadoutGeom(det, tg, ip, geometry_version, stName); 
1352         det->setHasCutouts(ncutouts>0);
1353         det->setNofREinStation(nMdt, nRpc, nTgc, nCsc);
1354         det->setStationEta(stationEta);
1355         det->setStationPhi(stationPhi);
1356         det->setParentStationPV(PVConstLink(ptrd));
1357         det->setParentMuonStation(mstat);
1358         int jobIndex = c->index;
1359         mstat->addMuonReadoutElement(det,jobIndex);
1360         if (m_debug) log<<MSG::DEBUG<<std::string(stName+techname)
1361                         <<" trying to build a TGC Id from stType/eta/phi "
1362                         <<stationType<<"/"
1363                         <<stationEta<<"/"
1364                         <<stationPhi<<"/ and /1/0/1   \n  Copy number is "<<geoid<<" tagName = "<<stag<<endreq;
1365         int gg = 1;
1366         int isStrip = 0;
1367         int ch = 1;
1368         Identifier id = tgc_id->channelID(stationType, stationEta,
1369                                           stationPhi, gg, isStrip, ch);
1370         det->setIdentifier(id);
1371         det->setLastInitField(4);
1372         m_manager->addTgcReadoutElement(det, id);
1373       }
1374                         
1375       if (lvr && RPCON){
1376         RpcComponent* rp = (RpcComponent*)c;
1377         int ndivy = rp->ndivy;
1378         int ndivz = rp->ndivz;
1379 //         if (geometry_version == "M28") 
1380 //      {
1381 //           GeoSerialDenominator* nm =
1382 //               new GeoSerialDenominator(stName + "_stName "+techname+" rpccomponent ");
1383 //           for (int j = 0; j < ndivz; j++) {
1384 //             for (int i = 0; i < ndivy; i++) {
1385 //               xfcomponent = xfrpccomponent[i+j*ndivy];
1386 //               ptrd->add(nm);
1387 //               ptrd->add(xfcomponent);
1388 //               ptrd->add(lvr);
1389 //             }
1390 //           }
1391 
1392 //      } 
1393 //      else 
1394 //      {
1395           if (ndivz!=1 || ndivy!=1 ) log << MSG::ERROR << " RPC segmentation z,y "
1396                                          << ndivz << " " << ndivy <<std::endl;
1397           double zpos = -length/2. + c->posy+c->dy/2.;
1398           double xpos = c->posx;
1399           // implement really the mirror symmetry
1400           if (is_mirrored) xpos = -xpos;
1401 
1402                 // ... putting back to here!
1403                 //                log<<MSG::DEBUG<<" In station "<<stName<<" with "
1404                 //                 <<nDoubletR<<" doubletR," 
1405                 //                   <<" RPC "<<(c->name).substr(3,2)
1406                 //                   <<" has swap flag = "<<rp->iswap
1407                 //                   <<" ypos, yd, zpos, zd "
1408                 //                   <<ypos<<" "<<yd<<" "<<zpos<<" "<<zd<<endreq;
1409                 //                    htcomponent = HepTranslateX3D(ypos)*HepTranslateY3D(xpos)
1410                 //                    *HepTranslateZ3D(zpos);
1411                 //                  xfcomponent = new GeoTransform(htcomponent);
1412 
1413           const RpcIdHelper* rpc_id = m_manager->rpcIdHelper();
1414           int stationEta = zi;
1415           int stationPhi = fi+1;
1416           int doubletR   = 1;
1417           int nfields    = 6;
1418           int doubletZ   = 0;
1419 
1420           if (nRpc > 1 && nDoubletR == 2 && ypos>0.) doubletR=2;
1421           ndbz[doubletR-1]++;
1422 
1423           if (zi <= 0 && !is_mirrored) {
1424             // the special cases 
1425             doubletZ = 1;
1426             if (zpos<-100.*mm)    doubletZ=2;
1427             if (fabs(xpos) > 100.*mm && ndbz[doubletR-1] > 2) {
1428               doubletZ = 3;
1429               nfields++;
1430             }
1431             if (fabs(xpos) > 100.*mm ) ndbz[doubletR-1]--;
1432 
1433           } else {
1434             doubletZ = 1;
1435             if (zpos > 100.*mm) doubletZ=2;
1436             if (fabs(xpos) > 100.*mm && ndbz[doubletR-1] > 2) {
1437               doubletZ = 3;
1438               nfields++;
1439             }
1440             if (fabs(xpos) > 100.*mm ) ndbz[doubletR-1]--;
1441           }
1442 
1443           int dbphi = 1;
1444           if (xpos > 100.*mm) dbphi = 2;
1445           // doublet phi not aware of pos. in space !!!
1446 
1447           int doubletPhi = dbphi;
1448           // doublet phi aware of pos. in space !!!
1449           if (zi < 0 && is_mirrored && doubletZ == 3) {
1450             doubletPhi++;
1451             if (doubletPhi > 2) doubletPhi = 1;
1452           } else if (zi < 0 && is_mirrored && doubletZ == 2 &&
1453                      doubletR == 1 && stName == "BMS6") {
1454             doubletPhi++;
1455             if (doubletPhi>2) doubletPhi=1;
1456           }
1457                     
1458           // never defined fields: set to the lower limit 
1459           int gasGap      = 1;
1460           int measuresPhi = 0;
1461           int strip       = 1;
1462 
1463           //int tag = rp->index + doubletR*100 + dbphi*1000;
1464           int geoid = 0;
1465           std::string stag;
1466           int tag = doubletZ + doubletR*100 + dbphi*1000;
1467           if (rp->iswap == -1) tag = -1*tag;
1468           stag = "SwapdbPdbRdbZ["+MuonGM::buildString(tag,0)
1469                   +"]"+techname+"rpccomponent";
1470           if (useAssemblies || isAssembly) {
1471             geoid = c->index;
1472           } 
1473           else 
1474           {
1475             int tag = rp->index + doubletR*100 + dbphi*1000;
1476             if (rp->iswap == -1) tag=-1*tag;
1477             geoid = tag;            
1478           }
1479 
1480           GeoNameTag* nm = new GeoNameTag(stag);   
1481           ptrd->add(new GeoIdentifierTag( geoid ));
1482           ptrd->add(nm);
1483 /*
1484           std::cout << " RPC position " << std::endl << 
1485                  (xfcomponent->getTransform())[0][0] << " " <<
1486                  (xfcomponent->getTransform())[0][1] << " " <<
1487                  (xfcomponent->getTransform())[0][2] << " " <<
1488                  (xfcomponent->getTransform())[0][3] << " " << std::endl <<
1489                  (xfcomponent->getTransform())[1][0] << " " <<
1490                  (xfcomponent->getTransform())[1][1] << " " <<
1491                  (xfcomponent->getTransform())[1][2] << " " <<
1492                  (xfcomponent->getTransform())[1][3] << " " << std::endl <<
1493                  (xfcomponent->getTransform())[2][0] << " " <<
1494                  (xfcomponent->getTransform())[2][1] << " " <<
1495                  (xfcomponent->getTransform())[2][2] << " " <<
1496                  (xfcomponent->getTransform())[2][3] << " " << std::endl;
1497 */
1498           xfaligncomponent->setDelta(HepTransform3D::Identity);
1499           //delete xfcomponent;
1500           ptrd->add(xfaligncomponent);
1501           ptrd->add(lvr);
1502                     
1503           RpcReadoutElement* det = new RpcReadoutElement(lvr, stName, zi, fi+1,
1504                                                          is_mirrored, m_manager);
1505           Position ip = mysql->GetStationPosition(stName.substr(0,3),fi,zi);
1506           setRpcReadoutGeom(det, rp, ip, geometry_version, m_manager);
1507           det->setHasCutouts(ncutouts > 0);
1508           det->setNofREinStation(nMdt, nRpc, nTgc, nCsc);
1509           det->setStationEta(stationEta);
1510           det->setStationPhi(stationPhi);
1511           det->setDoubletR(doubletR);
1512           det->setDoubletZ(doubletZ);
1513           det->setDoubletPhi(doubletPhi);
1514           if (m_debug) log << MSG::DEBUG << std::string(stName+techname)
1515                            << " trying to build a RPC Id from stType/eta/phi/dbR/dbZ/dbP "
1516                            << stationType << "/"
1517                            << stationEta << "/" << stationPhi << "/" << doubletR << "/"
1518                            << doubletZ << "/" << doubletPhi
1519                            << "///" << gasGap << "/" << measuresPhi << "/" << strip << "\n Copy number "
1520                            << geoid << " tagName= " << stag << endreq;
1521                     
1522           det->setParentStationPV(PVConstLink(ptrd));
1523           det->setParentMuonStation(mstat);
1524           int jobIndex = c->index;
1525           mstat->addMuonReadoutElement(det,jobIndex);
1526           Identifier id = rpc_id->channelID(stationType, stationEta,
1527                                             stationPhi, doubletR, doubletZ,
1528                                             doubletPhi, gasGap, measuresPhi, 
1529                                             strip);
1530           det->setIdentifier(id);
1531           det->setLastInitField(nfields);
1532                 //=========================
1533                 // A little debug section
1534 
1535                 //              std::cout << "ID = " << rpc_id->show_to_string(id) << std::endl;
1536                 //              HepPoint3D dummy=det->gasGapPos(id);
1537                 //              std::cout << " Rpcreadoutelement gas gap pos = "
1538                 //                      << dummy.x() << " " << dummy.y() << " "
1539                 //              << dummy.z() << std::endl;
1540                 //            dummy=det->stripPos(id);
1541                 //              std::cout << " Rpcreadoutelement strip pos = "
1542                 //                      << dummy.x() << " " << dummy.y() << " "
1543                 //              << dummy.z() << std::endl;
1544                 //=========================
1545           m_manager->addRpcReadoutElement(det, id);
1546           //        }
1547       }
1548 
1549       if (lvs && RPCON) {
1550         SupComponent* csup = (SupComponent*)c;
1551         std::string cname = csup->name;
1552         if (m_verbose) log << MSG::VERBOSE
1553                            << " yes, the component is a SupComponent named "
1554                            << cname << endreq;
1555         GeoNameTag* nm = new GeoNameTag(stName + "_stName "+techname+" supcomponent");
1556         ptrd->add(new GeoIdentifierTag(c->index));
1557         ptrd->add(nm);
1558         ptrd->add(xfcomponent);
1559         if (m_verbose) {
1560           log << MSG::VERBOSE << " register x" << endreq;
1561           log << MSG::VERBOSE << " register y" << endreq;
1562           log << MSG::VERBOSE << " register z" << endreq;
1563         }
1564         ptrd->add(lvs);
1565         if (m_verbose) log << MSG::VERBOSE << " register lvs" << endreq;
1566       }
1567 
1568       if (lvd && RPCON) {
1569         GeoNameTag* nm = new GeoNameTag(stName + "_stName "+techname+" dedcomponent");
1570         ptrd->add(new GeoIdentifierTag(c->index));
1571         ptrd->add(nm);
1572 /*
1573         std::cout << " DED position " <<
1574                  (xfcomponent->getTransform())[0][0] << " " <<
1575                  (xfcomponent->getTransform())[0][1] << " " <<
1576                  (xfcomponent->getTransform())[0][2] << " " <<
1577                  (xfcomponent->getTransform())[0][3] << " " << std::endl <<
1578                  (xfcomponent->getTransform())[1][0] << " " <<
1579                  (xfcomponent->getTransform())[1][1] << " " <<
1580                  (xfcomponent->getTransform())[1][2] << " " <<
1581                  (xfcomponent->getTransform())[1][3] << " " << std::endl <<
1582                  (xfcomponent->getTransform())[2][0] << " " <<
1583                  (xfcomponent->getTransform())[2][1] << " " <<
1584                  (xfcomponent->getTransform())[2][2] << " " <<
1585                  (xfcomponent->getTransform())[2][3] << " " << std::endl;
1586 */
1587         ptrd->add(xfcomponent);
1588         ptrd->add(lvd);
1589       }
1590 
1591       if (lvo) {
1592             // translate from AMDB chamber coordinates:
1593             //  (move chamber origin and swap axes around)
1594             // D-line gives AMDB coords of AMDB component origin
1595             // we need MuonGM coords of MuonGM component origin...
1596             // take off length/2, thickness/2 to get to AMDB chamber org
1597             // then put back GetLength()/2, GetThickness()/2 to get to
1598             //  component org.
1599             GeoNameTag* nm = new GeoNameTag(stName + "_stName "+techname+" component");
1600             ptrd->add(new GeoIdentifierTag(c->index));
1601             ptrd->add(nm);
1602 /*
1603             std::cout << techname << " position in " << stName << std::endl << 
1604                  (xfcomponent->getTransform())[0][0] << " " <<
1605                  (xfcomponent->getTransform())[0][1] << " " <<
1606                  (xfcomponent->getTransform())[0][2] << " " <<
1607                  (xfcomponent->getTransform())[0][3] << " " << std::endl <<
1608                  (xfcomponent->getTransform())[1][0] << " " <<
1609                  (xfcomponent->getTransform())[1][1] << " " <<
1610                  (xfcomponent->getTransform())[1][2] << " " <<
1611                  (xfcomponent->getTransform())[1][3] << " " << std::endl <<
1612                  (xfcomponent->getTransform())[2][0] << " " <<
1613                  (xfcomponent->getTransform())[2][1] << " " <<
1614                  (xfcomponent->getTransform())[2][2] << " " <<
1615                  (xfcomponent->getTransform())[2][3] << " " << std::endl;
1616 */
1617             ptrd->add(xfcomponent);
1618             ptrd->add(lvo);
1619       }
1620 
1621       if (lv) {
1622             GeoNameTag   *nm = new GeoNameTag(stName + "_stName "+techname+" component");
1623             ptrd->add(new GeoIdentifierTag(c->index));
1624             ptrd->add(nm);
1625             ptrd->add(xfcomponent);
1626             ptrd->add(lv);
1627       }
1628 
1629       for (size_t i = 0 ; i < vcutdef_todel.size(); i++) delete vcutdef_todel[i];
1630 
1631     } // End big loop over components
1632     return ptrd;
1633 }
1634 
1635 
1636 void MuonChamber::setCscReadoutGeom(CscReadoutElement* re, const CscComponent* cc, 
1637                                     const Position& ip, std::string gVersion, 
1638                                     std::string stName)
1639 {
1640   re->m_Ssize = cc->dx1;
1641   re->m_LongSsize = cc->dx2;
1642   re->m_Rsize = cc->dy;
1643   re->m_LongRsize = cc->dy;
1644   re->m_Zsize = cc->GetThickness();
1645   re->m_LongZsize = cc->GetThickness();
1646   re->m_RlengthUpToMaxWidth = cc->maxwdy;
1647   re->m_excent = cc->excent;
1648 
1649   // Csc features specific to this readout element
1650   std::string tname = cc->name;
1651   re->setTechnologyName(tname);
1652 
1653   if (ip.isAssigned) {
1654     re->setStationS(ip.shift);
1655   } else {
1656     std::cerr << " MuonChamber::setCscReadoutGeom: position not found " << std::endl;
1657     assert(0);
1658   }
1659 
1660   MYSQL* mysql = MYSQL::GetPointer();
1661   CSC* thisc = (CSC*)mysql->GetTechnology(tname);
1662   re->m_anodecathode_distance = thisc->anocathodist;
1663   re->m_ngasgaps = thisc->numOfLayers;
1664   re->m_nstriplayers = thisc->numOfLayers;
1665   re->m_nwirelayers = thisc->numOfLayers;
1666   re->m_roxacellwidth = thisc->roxacellwith;
1667   re->m_nEtastripsperlayer = thisc->nEtastrips;
1668   re->m_nPhistripsperlayer = thisc->nPhistrips;
1669   re->m_Etastrippitch = thisc->cathreadoutpitch;
1670   re->m_Phistrippitch = thisc->phireadoutpitch;
1671   re->m_Etastripwidth = re->m_Etastrippitch ;
1672   re->m_Phistripwidth = re->m_Phistrippitch ;
1673     
1674   if (gVersion.substr(0,3) == "P03") {
1675     if (stName.substr(0,3) == "CSS") re->m_nPhistripsperlayer = 28;
1676     else re->m_nPhistripsperlayer = 44;
1677   }
1678 
1679 }
1680 
1681 
1682 void MuonChamber::setMdtReadoutGeom(MdtReadoutElement* re, const MdtComponent* cc,
1683                                     const Position& ip)
1684 {
1685   re->m_Ssize = cc->dx1;
1686   re->m_LongSsize = cc->dx2;
1687 
1688   if (re->m_inBarrel) {
1689     re->m_Rsize = cc->GetThickness();
1690     re->m_LongRsize = cc->GetThickness();
1691     re->m_Zsize = cc->dy;
1692     re->m_LongZsize = cc->dy;
1693   } else {
1694     re->m_Rsize = cc->dy;
1695     re->m_LongRsize = cc->dy;
1696     re->m_Zsize = cc->GetThickness();
1697     re->m_LongZsize = cc->GetThickness();
1698   }
1699 
1700   re->m_cutoutShift = cc->cutoutTubeXShift;
1701   re->m_tubelenStepSize = cc->tubelenStepSize;
1702 
1703   if (ip.isAssigned) {
1704     re->setStationS(ip.shift);
1705   } else {
1706     std::cerr << " MuonChamber::setMdtReadoutGeom: position not found " << std::endl;
1707     assert(0);
1708   }
1709 
1710   std::string tname = cc->name;
1711   re->setTechnologyName(tname);
1712   MYSQL* mysql = MYSQL::GetPointer();
1713   MDT* thism = (MDT*)mysql->GetTechnology(tname);
1714   re->m_nlayers = thism->numOfLayers;
1715   re->m_tubepitch = thism->pitch;
1716   re->m_tubelayerpitch = thism->y[1]-thism->y[0];
1717   re->m_endpluglength = thism->tubeEndPlugLength;
1718   re->m_deadlength = cc->deadx; //thism->tubeDeadLength;
1719 
1720   if (re->m_inBarrel) {
1721     re->m_ntubesperlayer = int(re->m_Zsize/re->m_tubepitch);
1722     re->m_nsteps  =  1; // all tubes have the same length
1723     re->m_ntubesinastep = re->m_ntubesperlayer;
1724     re->m_tubelength[0] = re->m_Ssize;
1725   } else {
1726     re->m_ntubesperlayer = int(re->m_Rsize/re->m_tubepitch);
1727     re->m_nsteps = int(re->m_Rsize/re->m_tubelenStepSize);
1728     re->m_ntubesinastep = int(re->m_tubelenStepSize/re->m_tubepitch);
1729     re->m_tubelength[0] = re->m_Ssize;
1730     double diff = (re->m_LongSsize - re->m_Ssize) *
1731                   (re->m_LongRsize - re->m_tubepitch/2.)/re->m_LongRsize;
1732     for (int is = 0; is < re->m_nsteps; ++is) {
1733       double len = re->m_Ssize + is*diff/re->m_nsteps;
1734       re->m_tubelength[is] = len;
1735     }
1736   }
1737 
1738   for (int tl = 0; tl < re->m_nlayers; ++tl) {
1739     re->m_firstwire_x[tl] = thism->x[tl];
1740     re->m_firstwire_y[tl] = thism->y[tl];
1741   }
1742 
1743 }
1744 
1745 
1746 void MuonChamber::setRpcReadoutGeom(RpcReadoutElement* re, const RpcComponent* cc,
1747                                     const Position& ip, std::string gVersion,
1748                                     MuonDetectorManager* m_manager)
1749 {
1750   re->m_Ssize = cc->dx1;
1751   re->m_LongSsize = cc->dx2;
1752   re->m_Rsize = cc->GetThickness();
1753   re->m_LongRsize = cc->GetThickness();
1754   re->m_Zsize = cc->dy;
1755   re->m_LongZsize = cc->dy;
1756 
1757   re->m_hasDEDontop = true;
1758   if (cc->iswap == -1) re->m_hasDEDontop = false;
1759 
1760   if (ip.isAssigned) {
1761     re->setStationS(ip.shift);
1762   } else {
1763     std::cerr << " MuonChamber::setRpcReadoutGeom: position not found " << std::endl;
1764     assert(0);
1765   }
1766 
1767   std::string tname = cc->name;
1768   re->setTechnologyName(tname);
1769   MYSQL* mysql = MYSQL::GetPointer();
1770   RPC* thisr = (RPC*)mysql->GetTechnology(tname);
1771   re->m_nphigasgaps = thisr->NGasGaps_in_s;
1772   re->m_netagasgaps = thisr->NGasGaps_in_z;
1773   re->m_gasgapssize = re->m_Ssize/re->m_nphigasgaps - 2.*thisr->bakeliteframesize;
1774   re->m_gasgapzsize = re->m_Zsize/re->m_netagasgaps - 2.*thisr->bakeliteframesize;
1775   re->m_nphistrippanels = thisr->NstripPanels_in_s;
1776   re->m_netastrippanels = thisr->NstripPanels_in_z;
1777   re->m_phistrippitch = thisr->stripPitchS;
1778   re->m_etastrippitch = thisr->stripPitchZ;
1779   re->m_exthonthick = thisr->externalSupPanelThickness;
1780 
1781   const GenericRPCCache* rc = m_manager->getGenericRpcDescriptor();
1782   re->m_phistripwidth = re->m_phistrippitch - rc->stripSeparation;
1783   re->m_etastripwidth = re->m_etastrippitch - rc->stripSeparation;
1784   re->m_nphistripsperpanel = int((re->m_Ssize/re->m_nphistrippanels)/re->m_phistrippitch);
1785 
1786   while ((re->m_nphistripsperpanel%8) != 0) {re->m_nphistripsperpanel--;}
1787   re->m_netastripsperpanel = int((re->m_Zsize/re->m_netastrippanels)/re->m_etastrippitch);
1788   while ((re->m_netastripsperpanel%8) != 0) {re->m_netastripsperpanel--;}
1789 
1790   re->m_phipaneldead = re->m_Ssize/re->m_nphistrippanels
1791                      - re->m_nphistripsperpanel*re->m_phistrippitch
1792                      + rc->stripSeparation;
1793   re->m_phipaneldead = re->m_phipaneldead/2.;
1794   re->m_etapaneldead = re->m_Zsize/re->m_netastrippanels
1795                      - re->m_netastripsperpanel*re->m_etastrippitch
1796                      + rc->stripSeparation;
1797   re->m_etapaneldead = re->m_etapaneldead/2.;
1798   re->m_phistriplength = re->m_LongZsize/re->m_netastrippanels;
1799   re->m_etastriplength = re->m_LongSsize/re->m_nphistrippanels;
1800 
1801   // first strip position on each phi panel
1802   for (int is = 0; is < re->m_nphistrippanels; ++is) re->first_phistrip_s[is] = -999999.;
1803   re->first_phistrip_s[0] = -re->m_Ssize/2. + re->m_phipaneldead + re->m_phistripwidth/2.;
1804   if (re->m_nphistrippanels == 2)
1805      re->first_phistrip_s[1] = re->m_phipaneldead + re->m_phistripwidth/2.;
1806 
1807   double offset = 0.;
1808   if (gVersion.substr(0,3) == "P03") offset = rc->frontendBoardWidth;
1809 
1810   for (int is = 0; is < re->m_netastrippanels; ++is) re->phistrip_z[is] = -999999.;
1811   re->phistrip_z[0] = -re->m_Zsize/2. + offset + re->m_phistriplength/2.;
1812   if (re->m_netastrippanels == 2) re->phistrip_z[1] = re->m_Zsize/2. - offset - re->m_phistriplength/2.;
1813 
1814   // first strip position on each eta panel
1815   for (int is = 0; is < re->m_netastrippanels; ++is) re->first_etastrip_z[is] = -999999.;
1816   re->first_etastrip_z[0] = -re->m_Zsize/2. + re->m_etapaneldead + re->m_etastripwidth/2.;
1817   if (re->m_netastrippanels == 2)
1818     re->first_etastrip_z[1] = re->m_etapaneldead + re->m_etastripwidth/2.;
1819 
1820   for (int is = 0; is < re->m_nphistrippanels; ++is) re->etastrip_s[is] = -999999.;
1821   re->etastrip_s[0] = -re->m_Ssize/2. + offset + re->m_etastriplength/2.;
1822   if (re->m_nphistrippanels == 2) re->etastrip_s[1] = re->m_Ssize/2. - offset - re->m_etastriplength/2.;
1823 
1824 }
1825 
1826 
1827 void 
1828 MuonChamber::setTgcReadoutGeom(TgcReadoutElement* re, const TgcComponent* cc,
1829                                const Position& ip, std::string gVersion,
1830                                std::string stName)
1831 {
1832   re->m_Ssize = cc->dx1;
1833   re->m_LongSsize = cc->dx2;
1834   re->m_Rsize = cc->dy;
1835   re->m_LongRsize = cc->dy;
1836   re->m_Zsize = cc->GetThickness();
1837   re->m_LongZsize = cc->GetThickness();
1838 
1839   std::string tname = cc->name;
1840   int tname_index = MuonGM::strtoint(tname,3,2);
1841   re->setTechnologyName(tname);
1842 
1843   if (ip.isAssigned) {
1844     re->setStationS(ip.shift);
1845   } else {
1846     std::cerr <<" MuonChamber::setTgcReadoutGeom position not found " << std::endl;
1847     assert(0);
1848   }
1849 
1850   MYSQL* mysql = MYSQL::GetPointer();
1851   if (gVersion.substr(0,1) == "P" || gVersion.substr(0,3) == "CTB")
1852   {
1853     char index[2];
1854     sprintf(index,"%i", cc->index);
1855     re->m_readout_name = stName.substr(0,3) + index;
1856     re->m_readoutParams = mysql->GetTgcRPars(re->m_readout_name);
1857   } else {
1858     char index[2];
1859     sprintf(index,"%i", cc->index);
1860     //std::cout<<" cc->index = <"<<cc->index<<">"<<std::endl;
1861     re->m_readout_name = stName.substr(0,4) + "_" + index;
1862     re->m_readoutParams = mysql->GetTgcRPars(tname_index);
1863   }
1864 
1865   if (re->m_readoutParams == 0)
1866     std::cout << " MuonChamber::setTgcReadoutGeometry: no readoutParams found for key <"
1867               << re->m_readout_name << ">" << std::endl;
1868   else {
1869     re->m_readout_type = re->m_readoutParams->chamberType();
1870   }
1871 
1872   TGC* thist = (TGC*)(mysql->GetTechnology(tname));
1873   const std::size_t ncomp = (thist->materials).size();
1874   std::string::size_type npos;
1875   for (std::size_t i = 0; i < ncomp; ++i) {
1876     double newpos = -re->m_Zsize/2. + thist->positions[i] + thist->tck[i]/2.;
1877     const std::string& matname = thist->materials[i];
1878     if ((npos = matname.find("TGCGas")) != std::string::npos )
1879     {//here is a gasgap
1880       int Nstripplanes = 0;
1881       int Nwireplanes = 0;
1882       re->m_ngasgaps++;
1883       re->m_nwireplanes++;
1884       Nwireplanes = re->m_nwireplanes;
1885       re->m_nstripplanes++;
1886       Nstripplanes = re->m_nstripplanes;
1887       re->m_nstrips_per_plane[Nstripplanes-1] = 0;
1888       re->m_nwires_per_plane[Nwireplanes-1] = 0;
1889       re->m_nwiregangs_per_plane[Nwireplanes-1] = 0;
1890       re->m_strippitch[Nstripplanes-1] = 0.;
1891       re->m_stripwidth[Nstripplanes-1] = 0.;
1892       re->m_wirepitch[Nwireplanes-1] = re->m_readoutParams->wirePitch();