CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_9/src/Fireworks/Geometry/plugins/ValidateGeometry.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // $Id: ValidateGeometry.cc,v 1.35 2011/10/18 09:49:30 yana Exp $
00004 //
00005 
00006 #include "FWCore/Framework/interface/Frameworkfwd.h"
00007 #include "FWCore/Framework/interface/EDAnalyzer.h"
00008 #include "FWCore/Framework/interface/Event.h"
00009 #include "FWCore/Framework/interface/MakerMacros.h"
00010 #include "FWCore/Framework/interface/Event.h"
00011 #include "FWCore/Framework/interface/EventSetup.h"
00012 #include "FWCore/Framework/interface/ESHandle.h"
00013 
00014 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00015 
00016 #include "Geometry/DTGeometry/interface/DTGeometry.h"
00017 #include "Geometry/RPCGeometry/interface/RPCGeometry.h"
00018 #include "Geometry/CSCGeometry/interface/CSCGeometry.h"
00019 #include "Geometry/DTGeometry/interface/DTLayer.h"
00020 
00021 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00022 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00023 
00024 #include "Geometry/Records/interface/MuonGeometryRecord.h"
00025 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00026 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00027 
00028 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00029 #include "Geometry/TrackerGeometryBuilder/interface/PixelGeomDetUnit.h"
00030 #include "Geometry/TrackerGeometryBuilder/interface/StripGeomDetUnit.h"
00031 #include "Geometry/TrackerGeometryBuilder/interface/RectangularPixelTopology.h"
00032 #include "Geometry/TrackerGeometryBuilder/interface/StripGeomDetType.h"
00033 
00034 #include "Geometry/CommonTopologies/interface/PixelTopology.h"
00035 
00036 #include "Geometry/CommonTopologies/interface/StripTopology.h"
00037 #include "Geometry/CommonTopologies/interface/RectangularStripTopology.h"
00038 #include "Geometry/CommonTopologies/interface/TrapezoidalStripTopology.h"
00039 
00040 #include "Fireworks/Core/interface/FWGeometry.h"
00041 #include "Fireworks/Core/interface/fwLog.h"
00042 #include "Fireworks/Tracks/interface/TrackUtils.h"
00043 
00044 #include "DataFormats/HcalDetId/interface/HcalSubdetector.h"
00045 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00046 #include "DataFormats/MuonDetId/interface/DTWireId.h"
00047 #include "DataFormats/HcalDetId/interface/HcalCastorDetId.h"
00048 #include "DataFormats/HcalDetId/interface/HcalZDCDetId.h"
00049 
00050 #include "DataFormats/GeometrySurface/interface/RectangularPlaneBounds.h"
00051 #include "DataFormats/GeometrySurface/interface/TrapezoidalPlaneBounds.h"
00052 
00053 #include <string>
00054 #include <iostream>
00055 
00056 #include <TEveGeoNode.h>
00057 #include <TGeoVolume.h>
00058 #include <TGeoBBox.h>
00059 #include <TGeoArb8.h>
00060 #include <TFile.h>
00061 #include <TH1.h>
00062 
00063 class ValidateGeometry : public edm::EDAnalyzer 
00064 {
00065 public:
00066   explicit ValidateGeometry(const edm::ParameterSet&);
00067   ~ValidateGeometry();
00068 
00069 private:
00070   virtual void beginJob();
00071   virtual void analyze(const edm::Event&, const edm::EventSetup&);
00072   virtual void endJob();  
00073 
00074   void validateRPCGeometry(const int regionNumber, 
00075                            const char* regionName);
00076 
00077   void validateDTChamberGeometry();
00078   void validateDTLayerGeometry();
00079 
00080   void validateCSChamberGeometry(const int endcap,
00081                                  const char* detname);
00082 
00083   void validateCSCLayerGeometry(const int endcap,
00084                                 const char* detname);
00085 
00086   void validateCaloGeometry(DetId::Detector detector, int subdetector,
00087                             const char* detname);
00088 
00089   void validateTrackerGeometry(const TrackerGeometry::DetContainer& dets, 
00090                                const char* detname);
00091 
00092   void validateTrackerGeometry(const TrackerGeometry::DetUnitContainer& dets, 
00093                                const char* detname);
00094 
00095   void validatePixelTopology(const TrackerGeometry::DetContainer& dets,
00096                              const char* detname);
00097                    
00098   void validateStripTopology(const TrackerGeometry::DetContainer& dets,
00099                              const char* detname);
00100         
00101   void compareTransform(const GlobalPoint& point, const TGeoMatrix* matrix);
00102 
00103   void compareShape(const GeomDet* det, const float* shape);
00104   
00105   double getDistance(const GlobalPoint& point1, const GlobalPoint& point2);
00106 
00107   void makeHistograms(const char* detector);
00108   void makeHistogram(const std::string& name, std::vector<double>& data);
00109   
00110   std::string infileName_;
00111   std::string outfileName_;
00112 
00113   edm::ESHandle<RPCGeometry>     rpcGeometry_;
00114   edm::ESHandle<DTGeometry>      dtGeometry_;
00115   edm::ESHandle<CSCGeometry>     cscGeometry_;
00116   edm::ESHandle<CaloGeometry>    caloGeometry_;
00117   edm::ESHandle<TrackerGeometry> trackerGeometry_;
00118 
00119   FWGeometry fwGeometry_;
00120 
00121   TFile* outFile_;
00122 
00123   std::vector<double> globalDistances_;
00124   std::vector<double> topWidths_;
00125   std::vector<double> bottomWidths_;
00126   std::vector<double> lengths_;
00127   std::vector<double> thicknesses_;
00128 
00129   void clearData()
00130     {
00131       globalDistances_.clear();
00132       topWidths_.clear();
00133       bottomWidths_.clear();
00134       lengths_.clear();
00135       thicknesses_.clear();
00136     }
00137 
00138   bool dataEmpty()
00139     {
00140       return (globalDistances_.empty() && 
00141               topWidths_.empty() && 
00142               bottomWidths_.empty() && 
00143               lengths_.empty() && 
00144               thicknesses_.empty());
00145     }
00146 };
00147 
00148 
00149 ValidateGeometry::ValidateGeometry(const edm::ParameterSet& iConfig)
00150   : infileName_(iConfig.getUntrackedParameter<std::string>("infileName")),
00151     outfileName_(iConfig.getUntrackedParameter<std::string>("outfileName"))
00152 {
00153   fwGeometry_.loadMap(infileName_.c_str());
00154 
00155   outFile_ = new TFile(outfileName_.c_str(), "RECREATE");
00156 }
00157 
00158 
00159 ValidateGeometry::~ValidateGeometry()
00160 {}
00161 
00162 
00163 void 
00164 ValidateGeometry::analyze(const edm::Event& event, const edm::EventSetup& eventSetup)
00165 {
00166   eventSetup.get<MuonGeometryRecord>().get(rpcGeometry_);
00167 
00168   if ( rpcGeometry_.isValid() )
00169   {
00170     std::cout<<"Validating RPC -z endcap geometry"<<std::endl;
00171     validateRPCGeometry(-1, "RPC -z endcap");
00172 
00173     std::cout<<"Validating RPC +z endcap geometry"<<std::endl;
00174     validateRPCGeometry(+1, "RPC +z endcap");
00175 
00176     std::cout<<"Validating RPC barrel geometry"<<std::endl;
00177     validateRPCGeometry(0, "RPC barrel");
00178   }
00179   else
00180     fwLog(fwlog::kWarning)<<"Invalid RPC geometry"<<std::endl; 
00181 
00182 
00183   eventSetup.get<MuonGeometryRecord>().get(dtGeometry_);
00184 
00185   if ( dtGeometry_.isValid() )
00186   {
00187     std::cout<<"Validating DT chamber geometry"<<std::endl;
00188     validateDTChamberGeometry();
00189 
00190     std::cout<<"Validating DT layer geometry"<<std::endl;
00191     validateDTLayerGeometry();
00192   }
00193   else
00194     fwLog(fwlog::kWarning)<<"Invalid DT geometry"<<std::endl; 
00195 
00196 
00197   eventSetup.get<MuonGeometryRecord>().get(cscGeometry_);
00198 
00199   if ( cscGeometry_.isValid() )
00200   {
00201     std::cout<<"Validating CSC -z geometry"<<std::endl;
00202     validateCSChamberGeometry(-1, "CSC chamber -z endcap");
00203 
00204     std::cout<<"Validating CSC +z geometry"<<std::endl;
00205     validateCSChamberGeometry(+1, "CSC chamber +z endcap");
00206 
00207     std::cout<<"Validating CSC layer -z geometry"<<std::endl;
00208     validateCSCLayerGeometry(-1, "CSC layer -z endcap");
00209 
00210     std::cout<<"Validating CSC layer +z geometry"<<std::endl;
00211     validateCSCLayerGeometry(+1, "CSC layer +z endcap");
00212   }
00213   else
00214     fwLog(fwlog::kWarning)<<"Invalid CSC geometry"<<std::endl; 
00215 
00216   
00217   eventSetup.get<TrackerDigiGeometryRecord>().get(trackerGeometry_);
00218 
00219   if ( trackerGeometry_.isValid() )
00220   {
00221     std::cout<<"Validating TIB geometry and topology"<<std::endl;
00222     validateTrackerGeometry(trackerGeometry_->detsTIB(), "TIB");
00223     validateStripTopology(trackerGeometry_->detsTIB(), "TIB");
00224 
00225     std::cout<<"Validating TOB geometry and topology"<<std::endl;
00226     validateTrackerGeometry(trackerGeometry_->detsTOB(), "TOB");
00227     validateStripTopology(trackerGeometry_->detsTOB(), "TOB");
00228 
00229     std::cout<<"Validating TEC geometry and topology"<<std::endl;
00230     validateTrackerGeometry(trackerGeometry_->detsTEC(), "TEC");
00231     validateStripTopology(trackerGeometry_->detsTEC(), "TEC");
00232 
00233     std::cout<<"Validating TID geometry and topology"<<std::endl;
00234     validateTrackerGeometry(trackerGeometry_->detsTID(), "TID");
00235     validateStripTopology(trackerGeometry_->detsTID(), "TID");
00236 
00237     std::cout<<"Validating PXB geometry and topology"<<std::endl;
00238     validateTrackerGeometry(trackerGeometry_->detsPXB(), "PXB");
00239     validatePixelTopology(trackerGeometry_->detsPXB(), "PXB");
00240 
00241     std::cout<<"Validating PXF geometry and topology"<<std::endl;
00242     validateTrackerGeometry(trackerGeometry_->detsPXF(), "PXF");
00243     validatePixelTopology(trackerGeometry_->detsPXF(), "PXF");
00244   }
00245   else
00246     fwLog(fwlog::kWarning)<<"Invalid Tracker geometry"<<std::endl;
00247 
00248   eventSetup.get<CaloGeometryRecord>().get(caloGeometry_);
00249 
00250 
00251   if ( caloGeometry_.isValid() )
00252   {
00253     std::cout<<"Validating EB geometry"<<std::endl;
00254     validateCaloGeometry(DetId::Ecal, EcalBarrel, "EB");
00255 
00256     std::cout<<"Validating EE geometry"<<std::endl;
00257     validateCaloGeometry(DetId::Ecal, EcalEndcap, "EE");
00258 
00259     std::cout<<"Validating ES geometry"<<std::endl;
00260     validateCaloGeometry(DetId::Ecal, EcalPreshower, "ES");
00261 
00262     std::cout<<"Validating HB geometry"<<std::endl;
00263     validateCaloGeometry(DetId::Hcal, HcalBarrel, "HB");
00264   
00265     std::cout<<"Validating HE geometry"<<std::endl;
00266     validateCaloGeometry(DetId::Hcal, HcalEndcap, "HE");
00267 
00268     std::cout<<"Validating HO geometry"<<std::endl;
00269     validateCaloGeometry(DetId::Hcal, HcalOuter, "HO");
00270     
00271     std::cout<<"Validating HF geometry"<<std::endl;
00272     validateCaloGeometry(DetId::Hcal, HcalForward, "HF");
00273 
00274     std::cout<<"Validating Castor geometry"<<std::endl;
00275     validateCaloGeometry(DetId::Calo, HcalCastorDetId::SubdetectorId, "Castor");
00276 
00277     std::cout<<"Validating ZDC geometry"<<std::endl;
00278     validateCaloGeometry(DetId::Calo, HcalZDCDetId::SubdetectorId, "ZDC");
00279   }
00280   else
00281     fwLog(fwlog::kWarning)<<"Invalid Calo geometry"<<std::endl; 
00282 
00283 }
00284 
00285 
00286 void
00287 ValidateGeometry::validateRPCGeometry(const int regionNumber, const char* regionName)
00288 {
00289   clearData();
00290  
00291   std::vector<double> centers;
00292  
00293   std::vector<RPCRoll*> rolls = rpcGeometry_->rolls();
00294   
00295   for ( std::vector<RPCRoll*>::const_iterator it = rolls.begin(), 
00296                                            itEnd = rolls.end();
00297         it != itEnd; ++it )
00298   {
00299     const RPCRoll* roll = *it;
00300 
00301     if ( roll )
00302     {
00303       RPCDetId rpcDetId = roll->id();
00304 
00305       if ( rpcDetId.region() == regionNumber )
00306       {  
00307         const GeomDetUnit* det = rpcGeometry_->idToDetUnit(rpcDetId);
00308         GlobalPoint gp = det->surface().toGlobal(LocalPoint(0.0, 0.0, 0.0)); 
00309       
00310         const TGeoMatrix* matrix = fwGeometry_.getMatrix(rpcDetId.rawId());
00311 
00312         if ( ! matrix )
00313         {
00314           std::cout<<"Failed to get matrix of RPC with detid: "
00315                    << rpcDetId.rawId() <<std::endl;
00316           continue;
00317         }
00318 
00319         compareTransform(gp, matrix);
00320 
00321         const float* shape = fwGeometry_.getShapePars(rpcDetId.rawId());
00322 
00323         if ( ! shape )
00324         {
00325           std::cout<<"Failed to get shape of RPC with detid: "
00326                    << rpcDetId.rawId() <<std::endl;
00327           continue;
00328         }
00329       
00330         compareShape(det, shape);
00331 
00332         const float* parameters = fwGeometry_.getParameters(rpcDetId.rawId());
00333 
00334         if ( parameters == 0 )
00335         {
00336           std::cout<<"Parameters empty for RPC with detid: "
00337                    << rpcDetId.rawId() <<std::endl;
00338           continue;
00339         }
00340               
00341         // Yes, I know that below I'm comparing the equivalence
00342         // of floating point numbers
00343        
00344         int nStrips = roll->nstrips();
00345         assert(nStrips == parameters[0]); 
00346         
00347         float stripLength = roll->specificTopology().stripLength();
00348         assert(stripLength == parameters[1]);
00349 
00350         float pitch = roll->specificTopology().pitch();
00351         assert(pitch == parameters[2]);
00352 
00353         float offset = -0.5*nStrips*pitch;
00354 
00355         for ( int strip = 1; strip <= roll->nstrips(); ++strip )
00356         {
00357           LocalPoint centreOfStrip1 = roll->centreOfStrip(strip);        
00358           LocalPoint centreOfStrip2 = LocalPoint((strip-0.5)*pitch + offset, 0.0);
00359 
00360           centers.push_back(centreOfStrip1.x()-centreOfStrip2.x());
00361         }      
00362       }
00363     }
00364   }
00365 
00366   std::string hn(regionName);
00367   makeHistogram(hn+": centreOfStrip", centers);
00368  
00369 
00370   makeHistograms(regionName);
00371 }
00372 
00373 
00374 void 
00375 ValidateGeometry::validateDTChamberGeometry()
00376 {
00377   clearData();
00378 
00379   std::vector<DTChamber*> chambers = dtGeometry_->chambers();
00380   
00381   for ( std::vector<DTChamber*>::const_iterator it = chambers.begin(), 
00382                                              itEnd = chambers.end(); 
00383         it != itEnd; ++it)
00384   {
00385     const DTChamber* chamber = *it;
00386       
00387     if ( chamber )
00388     {
00389       DTChamberId chId = chamber->id();
00390       GlobalPoint gp = chamber->surface().toGlobal(LocalPoint(0.0, 0.0, 0.0)); 
00391      
00392       const TGeoMatrix* matrix = fwGeometry_.getMatrix(chId.rawId());
00393  
00394       if ( ! matrix )   
00395       {     
00396         std::cout<<"Failed to get matrix of DT chamber with detid: " 
00397                  << chId.rawId() <<std::endl;
00398         continue;
00399       }
00400 
00401       compareTransform(gp, matrix);
00402 
00403       const float* shape = fwGeometry_.getShapePars(chId.rawId());
00404 
00405       if ( ! shape )
00406       {
00407         std::cout<<"Failed to get shape of DT chamber with detid: "
00408                  << chId.rawId() <<std::endl;
00409         continue;
00410       }
00411       
00412       compareShape(chamber, shape);
00413     }
00414   }
00415 
00416   makeHistograms("DT chamber");
00417 }
00418 
00419 
00420 void 
00421 ValidateGeometry::validateDTLayerGeometry()
00422 {
00423   clearData();
00424   
00425   std::vector<double> wire_positions;
00426 
00427   std::vector<DTLayer*> layers = dtGeometry_->layers();
00428   
00429   for ( std::vector<DTLayer*>::const_iterator it = layers.begin(), 
00430                                            itEnd = layers.end(); 
00431         it != itEnd; ++it)
00432   {
00433     const DTLayer* layer = *it;
00434       
00435     if ( layer )
00436     {
00437       DTLayerId layerId = layer->id();
00438       GlobalPoint gp = layer->surface().toGlobal(LocalPoint(0.0, 0.0, 0.0)); 
00439      
00440       const TGeoMatrix* matrix = fwGeometry_.getMatrix(layerId.rawId());
00441  
00442       if ( ! matrix )   
00443       {     
00444         std::cout<<"Failed to get matrix of DT layer with detid: " 
00445                  << layerId.rawId() <<std::endl;
00446         continue;
00447       }
00448 
00449       compareTransform(gp, matrix);
00450 
00451       const float* shape = fwGeometry_.getShapePars(layerId.rawId());
00452 
00453       if ( ! shape )
00454       {
00455         std::cout<<"Failed to get shape of DT layer with detid: "
00456                  << layerId.rawId() <<std::endl;
00457         continue;
00458       }
00459       
00460       compareShape(layer, shape);
00461 
00462         
00463       const float* parameters = fwGeometry_.getParameters(layerId.rawId());
00464       
00465       if ( parameters == 0 )
00466       {
00467         std::cout<<"Parameters empty for DT layer with detid: " 
00468                  << layerId.rawId() <<std::endl;
00469         continue;
00470       }
00471            
00472       float width = layer->surface().bounds().width();
00473       assert(width == parameters[6]); 
00474 
00475       float thickness = layer->surface().bounds().thickness();
00476       assert(thickness == parameters[7]);
00477 
00478       float length = layer->surface().bounds().length();
00479       assert(length == parameters[8]);
00480 
00481       int firstChannel = layer->specificTopology().firstChannel();
00482       assert(firstChannel == parameters[3]);
00483 
00484       int lastChannel  = layer->specificTopology().lastChannel();
00485       int nChannels = parameters[5];
00486       assert(nChannels == (lastChannel-firstChannel)+1);
00487 
00488       for ( int wireN = firstChannel; wireN - lastChannel <= 0; ++wireN )
00489       {
00490         double localX1 = layer->specificTopology().wirePosition(wireN);
00491         double localX2 = (wireN -(firstChannel-1)-0.5)*parameters[0] - nChannels/2.0*parameters[0];
00492 
00493         wire_positions.push_back(localX1-localX2);
00494 
00495         //std::cout<<"wireN, localXpos: "<< wireN <<" "<< localX1 <<" "<< localX2 <<std::endl;
00496 
00497       }
00498     }
00499   }
00500 
00501   makeHistogram("DT layer wire localX", wire_positions);
00502 
00503   makeHistograms("DT layer");
00504 }
00505 
00506 
00507 void 
00508 ValidateGeometry::validateCSChamberGeometry(const int endcap, const char* detname)
00509 {
00510   clearData();
00511 
00512   std::vector<CSCChamber *> chambers = cscGeometry_->chambers();
00513      
00514   for ( std::vector<CSCChamber*>::const_iterator it = chambers.begin(), 
00515                                               itEnd = chambers.end(); 
00516         it != itEnd; ++it )
00517   {
00518     const CSCChamber* chamber = *it;
00519          
00520     if ( chamber && chamber->id().endcap() == endcap )
00521     {
00522       DetId detId = chamber->geographicalId();
00523       GlobalPoint gp = chamber->surface().toGlobal(LocalPoint(0.0,0.0,0.0));
00524 
00525       const TGeoMatrix* matrix = fwGeometry_.getMatrix(detId.rawId());
00526   
00527       if ( ! matrix ) 
00528       {     
00529         std::cout<<"Failed to get matrix of CSC chamber with detid: " 
00530                  << detId.rawId() <<std::endl;
00531         continue;
00532       }
00533 
00534       compareTransform(gp, matrix);
00535 
00536       const float* shape = fwGeometry_.getShapePars(detId.rawId());
00537 
00538       if ( ! shape )
00539       {
00540         std::cout<<"Failed to get shape of CSC chamber with detid: "
00541                  << detId.rawId() <<std::endl;
00542         continue;
00543       }
00544       
00545       compareShape(chamber, shape);
00546     }
00547   }
00548 
00549   makeHistograms(detname);
00550 }
00551 
00552 void 
00553 ValidateGeometry::validateCSCLayerGeometry(const int endcap, const char* detname)
00554 {
00555   clearData();
00556   std::vector<double> strip_positions;
00557   std::vector<double> wire_positions;
00558 
00559   std::vector<double> me11_wiresLocal;
00560   std::vector<double> me12_wiresLocal;
00561   std::vector<double> me13_wiresLocal;
00562   std::vector<double> me14_wiresLocal;
00563   std::vector<double> me21_wiresLocal;
00564   std::vector<double> me22_wiresLocal;
00565   std::vector<double> me31_wiresLocal;
00566   std::vector<double> me32_wiresLocal;
00567   std::vector<double> me41_wiresLocal;
00568   std::vector<double> me42_wiresLocal;
00569   
00570   std::vector<CSCLayer*> layers = cscGeometry_->layers();
00571      
00572   for ( std::vector<CSCLayer*>::const_iterator it = layers.begin(), 
00573                                             itEnd = layers.end(); 
00574         it != itEnd; ++it )
00575   {
00576     const CSCLayer* layer = *it;
00577          
00578     if ( layer && layer->id().endcap() == endcap )
00579     {
00580       DetId detId = layer->geographicalId();
00581       GlobalPoint gp = layer->surface().toGlobal(LocalPoint(0.0,0.0,0.0));
00582       
00583       const TGeoMatrix* matrix = fwGeometry_.getMatrix(detId.rawId());
00584   
00585       if ( ! matrix ) 
00586       {     
00587         std::cout<<"Failed to get matrix of CSC layer with detid: " 
00588                  << detId.rawId() <<std::endl;
00589         continue;
00590       }
00591 
00592       compareTransform(gp, matrix);
00593       
00594       const float* shape = fwGeometry_.getShapePars(detId.rawId());
00595 
00596       if ( ! shape )
00597       {
00598         std::cout<<"Failed to get shape of CSC layer with detid: "
00599                  << detId.rawId() <<std::endl;
00600         continue;
00601       }
00602       
00603       compareShape(layer, shape);
00604 
00605       double length;
00606  
00607       if ( shape[0] == 1 )
00608       {
00609         length = shape[4];
00610       }
00611        
00612       else
00613       {      
00614         std::cout<<"Failed to get trapezoid from shape for CSC layer with detid: "
00615                  << detId.rawId() <<std::endl;
00616         continue;
00617       }
00618 
00619       const float* parameters = fwGeometry_.getParameters(detId.rawId());
00620 
00621       if ( parameters == 0 )
00622       {
00623         std::cout<<"Parameters empty for CSC layer with detid: "
00624                  << detId.rawId() <<std::endl;
00625         continue;
00626       }
00627 
00628       int yAxisOrientation = layer->geometry()->topology()->yAxisOrientation();
00629       assert(yAxisOrientation == parameters[0]);
00630      
00631       float centreToIntersection = layer->geometry()->topology()->centreToIntersection();
00632       assert(centreToIntersection == parameters[1]);
00633 
00634       float yCentre = layer->geometry()->topology()->yCentreOfStripPlane();
00635       assert(yCentre == parameters[2]);
00636 
00637       float phiOfOneEdge = layer->geometry()->topology()->phiOfOneEdge();
00638       assert(phiOfOneEdge == parameters[3]);
00639 
00640       float stripOffset = layer->geometry()->topology()->stripOffset();
00641       assert(stripOffset == parameters[4]);
00642 
00643       float angularWidth = layer->geometry()->topology()->angularWidth();
00644       assert(angularWidth == parameters[5]);
00645 
00646       for ( int nStrip = 1; nStrip <= layer->geometry()->numberOfStrips(); 
00647             ++nStrip )
00648       {
00649         float xOfStrip1 = layer->geometry()->xOfStrip(nStrip);
00650       
00651         double stripAngle = phiOfOneEdge + yAxisOrientation*(nStrip-(0.5-stripOffset))*angularWidth;
00652         double xOfStrip2 = yAxisOrientation*(centreToIntersection-yCentre)*tan(stripAngle);
00653 
00654         strip_positions.push_back(xOfStrip1-xOfStrip2);
00655       }
00656 
00657       int station = layer->id().station();
00658       int ring    = layer->id().ring();
00659 
00660       double wireSpacingInGroup = layer->geometry()->wireTopology()->wireSpacing();
00661       assert(wireSpacingInGroup == parameters[6]);
00662 
00663       double wireSpacing = 0.0;
00664       // we calculate an average wire group 
00665       // spacing from radialExtentOfTheWirePlane / numOfWireGroups
00666       
00667       double extentOfWirePlane = 0.0;
00668 
00669       if ( ring == 2 )
00670       {
00671         if ( station == 1 )
00672           extentOfWirePlane = 174.81; //wireSpacing = 174.81/64;
00673         else
00674           extentOfWirePlane = 323.38; //wireSpacing = 323.38/64;
00675       }
00676       else if ( station == 1 && (ring == 1 || ring == 4))
00677         extentOfWirePlane = 150.5; //wireSpacing = 150.5/48;
00678       else if ( station == 1 && ring == 3 )
00679         extentOfWirePlane = 164.47; //wireSpacing = 164.47/32;
00680       else if ( station == 2 && ring == 1 )
00681         extentOfWirePlane = 189.97; //wireSpacing = 189.97/112;
00682       else if ( station == 3 && ring == 1 )
00683         extentOfWirePlane = 170.01; //wireSpacing = 170.01/96;
00684       else if ( station == 4 && ring == 1 )
00685         extentOfWirePlane = 149.73; //wireSpacing = 149.73/96;
00686 
00687       float wireAngle = layer->geometry()->wireTopology()->wireAngle();
00688       assert(wireAngle == parameters[7]);
00689 
00690       //float cosWireAngle = cos(wireAngle);
00691 
00692       /* NOTE
00693          Some parameters don't seem available in a public interface
00694          so have to perhaps hard-code. This may not be too bad as there
00695          seems to be a lot of degeneracy. 
00696       */
00697 
00698       double alignmentPinToFirstWire;
00699       double yAlignmentFrame = 3.49;
00700    
00701       if ( station == 1 ) 
00702       { 
00703         if ( ring == 1 || ring == 4 )
00704         {
00705           alignmentPinToFirstWire = 1.065;
00706           yAlignmentFrame = 0.0;
00707         }
00708         
00709         else // ME12, ME 13 
00710           alignmentPinToFirstWire = 2.85;
00711       }
00712 
00713       else if ( station == 4 && ring == 1 )
00714         alignmentPinToFirstWire = 3.04;
00715       
00716       else if ( station == 3 && ring == 1 )
00717         alignmentPinToFirstWire =  2.84;
00718       
00719       else  // ME21, ME22, ME32, ME42 
00720         alignmentPinToFirstWire = 2.87;
00721        
00722       double yOfFirstWire = (yAlignmentFrame-length) + alignmentPinToFirstWire;
00723 
00724       int nWireGroups = layer->geometry()->numberOfWireGroups();
00725       double E = extentOfWirePlane/nWireGroups;
00726 
00727       for ( int nWireGroup = 1; nWireGroup <= nWireGroups; ++nWireGroup )
00728       {         
00729         LocalPoint centerOfWireGroup = layer->geometry()->localCenterOfWireGroup(nWireGroup); 
00730         double yOfWire1 = centerOfWireGroup.y(); 
00731 
00732         //double yOfWire2 = (-0.5 - (nWireGroups*0.5 - 1) + (nWireGroup-1))*E; 
00733         //yOfWire2 += 0.5*E;
00734         double yOfWire2 = yOfFirstWire + ((nWireGroup-1)*E);
00735         yOfWire2 += wireSpacing*0.5;
00736 
00737         double ydiff_local = yOfWire1 - yOfWire2; 
00738         wire_positions.push_back(ydiff_local);
00739 
00740         //GlobalPoint globalPoint = layer->surface().toGlobal(LocalPoint(0.0,yOfWire1,0.0));
00741 
00742         /*
00743         float fwLocalPoint[3] = 
00744         {
00745           0.0, yOfWire2, 0.0
00746         };
00747         
00748         float fwGlobalPoint[3]; 
00749         fwGeometry_.localToGlobal(detId.rawId(), fwLocalPoint, fwGlobalPoint);
00750         double ydiff_global = globalPoint.y() - fwGlobalPoint[1]; 
00751         */
00752 
00753         if ( station == 1 )
00754         {
00755           if ( ring == 1 )
00756           {
00757             me11_wiresLocal.push_back(ydiff_local);
00758           }
00759           else if ( ring == 2 )
00760           {
00761             me12_wiresLocal.push_back(ydiff_local);
00762           }
00763           else if ( ring == 3 )
00764           {
00765             me13_wiresLocal.push_back(ydiff_local);
00766           }
00767           else if ( ring == 4 )
00768           {
00769             me14_wiresLocal.push_back(ydiff_local);
00770           }
00771         }
00772         else if ( station == 2 ) 
00773         {
00774           if ( ring == 1 )
00775           {
00776             me21_wiresLocal.push_back(ydiff_local);
00777           }
00778           else if ( ring == 2 )
00779           {
00780             me22_wiresLocal.push_back(ydiff_local);
00781           }
00782         }
00783         else if ( station == 3 )
00784         {
00785           if ( ring == 1 )
00786           {
00787             me31_wiresLocal.push_back(ydiff_local);
00788           }
00789           else if ( ring == 2 )
00790           {
00791             me32_wiresLocal.push_back(ydiff_local);
00792           }
00793         }
00794         else if ( station == 4 )
00795         {
00796           if ( ring == 1 )
00797           {
00798             me41_wiresLocal.push_back(ydiff_local);
00799           }
00800           else if ( ring == 2 )
00801           {
00802             me42_wiresLocal.push_back(ydiff_local);
00803           }
00804         }
00805       } 
00806     }
00807   }
00808   
00809   std::string hn(detname);
00810   makeHistogram(hn+": xOfStrip", strip_positions);
00811 
00812   makeHistogram(hn+": local yOfWire", wire_positions);
00813   
00814   makeHistogram("ME11: local yOfWire", me11_wiresLocal);
00815   makeHistogram("ME12: local yOfWire", me12_wiresLocal);
00816   makeHistogram("ME13: local yOfWire", me13_wiresLocal);
00817   makeHistogram("ME14: local yOfWire", me14_wiresLocal);
00818   makeHistogram("ME21: local yOfWire", me21_wiresLocal);
00819   makeHistogram("ME22: local yOfWire", me22_wiresLocal);
00820   makeHistogram("ME31: local yOfWire", me31_wiresLocal);
00821   makeHistogram("ME32: local yOfWire", me32_wiresLocal);
00822   makeHistogram("ME41: local yOfWire", me41_wiresLocal);
00823   makeHistogram("ME42: local yOfWire", me42_wiresLocal);
00824 
00825   makeHistograms(detname);
00826 }
00827 
00828 void 
00829 ValidateGeometry::validateCaloGeometry(DetId::Detector detector, 
00830                                        int subdetector,
00831                                        const char* detname)
00832 {
00833   clearData();
00834 
00835   const CaloSubdetectorGeometry* geometry = 
00836     caloGeometry_->getSubdetectorGeometry(detector, subdetector);
00837 
00838   const std::vector<DetId>& ids = geometry->getValidDetIds(detector, subdetector);
00839 
00840   for (std::vector<DetId>::const_iterator it = ids.begin(), 
00841                                         iEnd = ids.end(); 
00842        it != iEnd; ++it) 
00843   {
00844     unsigned int rawId = (*it).rawId();
00845 
00846     const float* points = fwGeometry_.getCorners(rawId);
00847 
00848     if ( points == 0 )
00849     { 
00850       std::cout <<"Failed to get points of "<< detname 
00851                 <<" element with detid: "<< rawId <<std::endl;
00852       continue;
00853     }
00854 
00855     const CaloCellGeometry* cellGeometry = geometry->getGeometry(*it);
00856     const CaloCellGeometry::CornersVec& corners = cellGeometry->getCorners();
00857     
00858     assert(corners.size() == 8);
00859     
00860     for ( unsigned int i = 0, offset = 0; i < 8; ++i )
00861     {
00862       offset = 2*i;
00863 
00864       double distance = getDistance(GlobalPoint(points[i+offset], points[i+1+offset], points[i+2+offset]), 
00865                                     GlobalPoint(corners[i].x(), corners[i].y(), corners[i].z()));
00866      
00867       globalDistances_.push_back(distance);
00868     }
00869   }
00870 
00871   makeHistograms(detname);
00872 }
00873 
00874 
00875 void
00876 ValidateGeometry::validateTrackerGeometry(const TrackerGeometry::DetContainer& dets,
00877                                           const char* detname)
00878 {
00879   clearData();
00880 
00881   for ( TrackerGeometry::DetContainer::const_iterator it = dets.begin(), 
00882                                                    itEnd = dets.end(); 
00883         it != itEnd; ++it )
00884   {
00885     GlobalPoint gp = (trackerGeometry_->idToDet((*it)->geographicalId()))->surface().toGlobal(LocalPoint(0.0,0.0,0.0));
00886     unsigned int rawId = (*it)->geographicalId().rawId();
00887 
00888     const TGeoMatrix* matrix = fwGeometry_.getMatrix(rawId);
00889 
00890     if ( ! matrix )
00891     {
00892       std::cout <<"Failed to get matrix of "<< detname 
00893                 <<" element with detid: "<< rawId <<std::endl;
00894       continue;
00895     }
00896 
00897     compareTransform(gp, matrix);
00898 
00899     const float* shape = fwGeometry_.getShapePars(rawId);
00900 
00901     if ( ! shape )
00902     {
00903       std::cout<<"Failed to get shape of "<< detname 
00904                <<" element with detid: "<< rawId <<std::endl;
00905       continue;
00906     }
00907 
00908     compareShape(*it, shape);
00909   }
00910   
00911   makeHistograms(detname);
00912 }
00913 
00914 
00915 void
00916 ValidateGeometry::validateTrackerGeometry(const TrackerGeometry::DetUnitContainer& dets,
00917                                           const char* detname)
00918 {
00919   clearData();
00920 
00921   for ( TrackerGeometry::DetUnitContainer::const_iterator it = dets.begin(), 
00922                                                        itEnd = dets.end(); 
00923         it != itEnd; ++it )
00924   {
00925     GlobalPoint gp = (trackerGeometry_->idToDet((*it)->geographicalId()))->surface().toGlobal(LocalPoint(0.0,0.0,0.0));
00926     unsigned int rawId = (*it)->geographicalId().rawId();
00927 
00928     const TGeoMatrix* matrix = fwGeometry_.getMatrix(rawId);
00929 
00930     if ( ! matrix )
00931     {
00932       std::cout<< "Failed to get matrix of "<< detname 
00933                <<" element with detid: "<< rawId <<std::endl;
00934       continue;
00935     }
00936 
00937     compareTransform(gp, matrix);
00938 
00939 
00940     const float* shape = fwGeometry_.getShapePars(rawId);
00941 
00942     if ( ! shape )
00943     {
00944       std::cout<<"Failed to get shape of "<< detname 
00945                <<" element with detid: "<< rawId <<std::endl;
00946       continue;
00947     }
00948 
00949     compareShape(*it, shape);
00950   }
00951   
00952   makeHistograms(detname);
00953 }
00954 
00955 void 
00956 ValidateGeometry::validatePixelTopology(const TrackerGeometry::DetContainer& dets,
00957                                         const char* detname)
00958 {
00959   std::vector<double> pixelLocalXs;
00960   std::vector<double> pixelLocalYs;
00961 
00962   for ( TrackerGeometry::DetContainer::const_iterator it = dets.begin(),
00963                                                    itEnd = dets.end();
00964         it != itEnd; ++it )
00965   {
00966     unsigned int rawId = (*it)->geographicalId().rawId();
00967 
00968     const float* parameters = fwGeometry_.getParameters(rawId);
00969 
00970     if ( parameters == 0 )
00971     {
00972       std::cout<<"Parameters empty for "<< detname <<" element with detid: "
00973                << rawId <<std::endl;
00974       continue;
00975     }
00976 
00977     if ( const PixelGeomDetUnit* det = 
00978          dynamic_cast<const PixelGeomDetUnit*>(trackerGeometry_->idToDetUnit((*it)->geographicalId())) )
00979     {           
00980       if ( const PixelTopology* rpt = &det->specificTopology() )
00981       { 
00982         int nrows = rpt->nrows();
00983         int ncolumns = rpt->ncolumns();
00984         
00985         assert(parameters[0] == nrows);
00986         assert(parameters[1] == ncolumns);
00987         
00988         for ( int row = 1; row <= nrows; ++row )
00989         {
00990           for ( int column = 1; column <= ncolumns; ++column )
00991           {
00992             LocalPoint localPoint = rpt->localPosition(MeasurementPoint(row, column));
00993 
00994             pixelLocalXs.push_back(localPoint.x() - fireworks::pixelLocalX(row, nrows));
00995             pixelLocalYs.push_back(localPoint.y() - fireworks::pixelLocalY(column, ncolumns));
00996            }
00997         }
00998       }
00999        
01000       else
01001         std::cout<<"No topology for "<< detname <<" "<< rawId <<std::endl; 
01002     }
01003 
01004     else
01005       std::cout<<"No geomDetUnit for "<< detname <<" "<< rawId <<std::endl;
01006   }
01007 
01008   std::string hn(detname);
01009   makeHistogram(hn+" pixelLocalX", pixelLocalXs);
01010   makeHistogram(hn+" pixelLocalY", pixelLocalYs);
01011 }
01012 
01013 void 
01014 ValidateGeometry::validateStripTopology(const TrackerGeometry::DetContainer& dets,
01015                                         const char* detname)
01016 {
01017   std::vector<double> radialStripLocalXs;
01018   std::vector<double> rectangularStripLocalXs;
01019 
01020   for ( TrackerGeometry::DetContainer::const_iterator it = dets.begin(),
01021                                                    itEnd = dets.end();
01022         it != itEnd; ++it )
01023   {
01024     unsigned int rawId = (*it)->geographicalId().rawId();
01025     
01026     const float* parameters = fwGeometry_.getParameters(rawId);
01027 
01028     if ( parameters == 0 )
01029     {    
01030       std::cout<<"Parameters empty for "<< detname <<" element with detid: "
01031                << rawId <<std::endl;
01032       continue;
01033     }
01034 
01035     if ( const StripGeomDetUnit* det = 
01036          dynamic_cast<const StripGeomDetUnit*>(trackerGeometry_->idToDet((*it)->geographicalId())) )
01037       {
01038       // NOTE: why the difference in dets vs. units between these and pixels? The dynamic cast above 
01039       // fails for many of the detids...
01040       
01041       const StripTopology* st = dynamic_cast<const StripTopology*>(&det->specificTopology()); 
01042       
01043       if ( st ) 
01044       {
01045         //assert(parameters[0] == 0);
01046         int nstrips = st->nstrips();
01047         assert(parameters[1] == nstrips);                             
01048         assert(parameters[2] == st->stripLength());
01049         
01050         if( const RadialStripTopology* rst = dynamic_cast<const RadialStripTopology*>(&(det->specificType().specificTopology())) ) 
01051         {
01052           assert(parameters[0] == 1);
01053           assert(parameters[3] == rst->yAxisOrientation());
01054           assert(parameters[4] == rst->originToIntersection());
01055           assert(parameters[5] == rst->phiOfOneEdge());
01056           assert(parameters[6] == rst->angularWidth());
01057 
01058           for ( uint16_t strip = 1; strip <= nstrips; ++strip )
01059           {
01060             float stripAngle1 = rst->stripAngle(strip);
01061             float stripAngle2 = parameters[5] + parameters[3]*strip*parameters[6];
01062           
01063             assert((stripAngle1-stripAngle2) == 0); 
01064             
01065             LocalPoint stripPosition = st->localPosition(strip);
01066             
01067             float stripX = parameters[3]*parameters[4]*tan(stripAngle2);
01068             radialStripLocalXs.push_back(stripPosition.x()-stripX);
01069           }
01070         }
01071          
01072         else if( dynamic_cast<const RectangularStripTopology*>(&(det->specificType().specificTopology())) )
01073         {
01074           assert(parameters[0] == 2);
01075           assert(parameters[3] == st->pitch());
01076 
01077           for ( uint16_t strip = 1; strip <= nstrips; ++strip )
01078           {
01079             LocalPoint stripPosition = st->localPosition(strip);
01080             float stripX = -parameters[1]*0.5*parameters[3];
01081             stripX += strip*parameters[3];
01082             rectangularStripLocalXs.push_back(stripPosition.x()-stripX);
01083           }
01084         }
01085         
01086         else if( dynamic_cast<const TrapezoidalStripTopology*>(&(det->specificType().specificTopology())) )
01087         {
01088           assert(parameters[0] == 3); 
01089           assert(parameters[3] == st->pitch());                               
01090         }
01091         
01092         else
01093           std::cout<<"Failed to get pitch for "<< detname <<" "<< rawId <<std::endl;
01094       }
01095       
01096       else
01097         std::cout<<"Failed cast to StripTopology for "<< detname <<" "<< rawId <<std::endl;
01098     }
01099     
01100     //else
01101     //  std::cout<<"Failed cast to StripGeomDetUnit for "<< detname <<" "<< rawId <<std::endl;
01102   }
01103 
01104   std::string hn(detname);
01105   makeHistogram(hn+" radial strip localX", radialStripLocalXs);
01106   makeHistogram(hn+" rectangular strip localX", rectangularStripLocalXs);
01107 }
01108 
01109 
01110 void    
01111 ValidateGeometry::compareTransform(const GlobalPoint& gp,
01112                                    const TGeoMatrix* matrix)
01113 {
01114   double local[3] = 
01115     {
01116       0.0, 0.0, 0.0
01117     };
01118       
01119   double global[3];
01120 
01121   matrix->LocalToMaster(local, global);
01122 
01123   double distance = getDistance(GlobalPoint(global[0], global[1], global[2]), gp);
01124   globalDistances_.push_back(distance);
01125 }
01126 
01127 void 
01128 ValidateGeometry::compareShape(const GeomDet* det, const float* shape)
01129 {
01130   double shape_topWidth;
01131   double shape_bottomWidth;
01132   double shape_length;
01133   double shape_thickness;
01134 
01135   if ( shape[0] == 1 )
01136   {
01137     shape_topWidth = shape[2];
01138     shape_bottomWidth = shape[1];
01139     shape_length = shape[4];
01140     shape_thickness = shape[3];
01141   }
01142   
01143   else if ( shape[0] == 2 )
01144   {
01145     shape_topWidth = shape[1];
01146     shape_bottomWidth = shape[1];
01147     shape_length = shape[2];
01148     shape_thickness = shape[3];
01149   }
01150   
01151   else
01152   {
01153     std::cout<<"Failed to get box or trapezoid from shape"<<std::endl;
01154     return;
01155   }
01156 
01157   double topWidth, bottomWidth;
01158   double length, thickness;
01159 
01160   const Bounds* bounds = &(det->surface().bounds());
01161  
01162   if ( const TrapezoidalPlaneBounds* tpbs = dynamic_cast<const TrapezoidalPlaneBounds*>(bounds) )
01163   {
01164     std::vector<float> ps = tpbs->parameters();
01165 
01166     assert(ps.size() == 4);
01167     
01168     bottomWidth = ps[0];
01169     topWidth = ps[1];
01170     thickness = ps[2];
01171     length = ps[3];
01172   }
01173 
01174   else if ( (dynamic_cast<const RectangularPlaneBounds*>(bounds)) )
01175   {
01176     length = det->surface().bounds().length()*0.5;
01177     topWidth = det->surface().bounds().width()*0.5;
01178     bottomWidth = topWidth;
01179     thickness = det->surface().bounds().thickness()*0.5;
01180   }
01181   
01182   else
01183   {
01184     std::cout<<"Failed to get bounds"<<std::endl;
01185     return;
01186   }
01187    
01188   //assert((tgeotrap && trapezoid) || (tgeobbox && rectangle)); 
01189 
01190   /*
01191   std::cout<<"topWidth: "<< shape_topWidth <<" "<< topWidth <<std::endl;
01192   std::cout<<"bottomWidth: "<< shape_bottomWidth <<" "<< bottomWidth <<std::endl;
01193   std::cout<<"length: "<< shape_length <<" "<< length <<std::endl;
01194   std::cout<<"thickness: "<< shape_thickness <<" "<< thickness <<std::endl;
01195   */
01196 
01197   topWidths_.push_back(fabs(shape_topWidth - topWidth));
01198   bottomWidths_.push_back(fabs(shape_bottomWidth - bottomWidth));
01199   lengths_.push_back(fabs(shape_length - length));
01200   thicknesses_.push_back(fabs(shape_thickness - thickness));
01201 
01202   return;
01203 }
01204 
01205 
01206 
01207 
01208 double 
01209 ValidateGeometry::getDistance(const GlobalPoint& p1, const GlobalPoint& p2)
01210 {
01211   /*
01212   std::cout<<"X: "<< p1.x() <<" "<< p2.x() <<std::endl;
01213   std::cout<<"Y: "<< p1.y() <<" "<< p2.y() <<std::endl;
01214   std::cout<<"Z: "<< p1.z() <<" "<< p2.z() <<std::endl;
01215   */
01216 
01217   return sqrt((p1.x()-p2.x())*(p1.x()-p2.x())+
01218               (p1.y()-p2.y())*(p1.y()-p2.y())+
01219               (p1.z()-p2.z())*(p1.z()-p2.z()));
01220 }
01221 
01222 
01223 void
01224 ValidateGeometry::makeHistograms(const char* detector)
01225 {
01226   outFile_->cd();
01227 
01228   std::string d(detector);
01229   
01230   std::string gdn = d+": distance between points in global coordinates";
01231   makeHistogram(gdn, globalDistances_);
01232 
01233   std::string twn = d + ": absolute difference between top widths (along X)";
01234   makeHistogram(twn, topWidths_);
01235 
01236   std::string bwn = d + ": absolute difference between bottom widths (along X)";
01237   makeHistogram(bwn, bottomWidths_);
01238 
01239   std::string ln = d + ": absolute difference between lengths (along Y)";
01240   makeHistogram(ln, lengths_);
01241 
01242   std::string tn = d + ": absolute difference between thicknesses (along Z)";
01243   makeHistogram(tn, thicknesses_);
01244 
01245   return;
01246 }
01247 
01248 
01249 void
01250 ValidateGeometry::makeHistogram(const std::string& name, std::vector<double>& data)
01251 {
01252   if ( data.empty() )
01253     return;
01254 
01255   std::vector<double>::iterator it;
01256   
01257   it = std::min_element(data.begin(), data.end());
01258   double minE = *it;
01259 
01260   it = std::max_element(data.begin(), data.end());
01261   double maxE = *it;
01262 
01263   std::vector<double>::iterator itEnd = data.end();
01264 
01265   TH1D hist(name.c_str(), name.c_str(), 100, minE*(1+0.10), maxE*(1+0.10));
01266   
01267   for ( it = data.begin(); it != itEnd; ++it )
01268     hist.Fill(*it);
01269  
01270   hist.GetXaxis()->SetTitle("[cm]");
01271   hist.Write();
01272 }
01273 
01274 void 
01275 ValidateGeometry::beginJob()
01276 {
01277   outFile_->cd();
01278 }
01279 
01280 
01281 void 
01282 ValidateGeometry::endJob() 
01283 {
01284   std::cout<<"Done. "<<std::endl;
01285   std::cout<<"Results written to "<< outfileName_ <<std::endl;
01286   outFile_->Close();
01287 }
01288 
01289 DEFINE_FWK_MODULE(ValidateGeometry);
01290