Go to the documentation of this file.00001 #include <iostream>
00002 #include <fstream>
00003 #include <sstream>
00004 #include <vector>
00005 #include <string>
00006 #include <stdexcept>
00007 #include <cstring>
00008 #include <cstdlib>
00009 #include <boost/tuple/tuple.hpp>
00010 #include <boost/format.hpp>
00011
00012 #include "FWCore/Framework/interface/Event.h"
00013 #include "FWCore/Framework/interface/EventSetup.h"
00014 #include "FWCore/Framework/interface/ESTransientHandle.h"
00015 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00016 #include "FWCore/Utilities/interface/EDMException.h"
00017
00018 #include "DetectorDescription/Core/interface/DDFilteredView.h"
00019 #include "DetectorDescription/Core/interface/DDCompactView.h"
00020 #include "DetectorDescription/Core/interface/DDMaterial.h"
00021 #include "Geometry/Records/interface/IdealGeometryRecord.h"
00022
00023 #include "SimDataFormats/ValidationFormats/interface/MaterialAccountingStep.h"
00024 #include "SimDataFormats/ValidationFormats/interface/MaterialAccountingTrack.h"
00025 #include "MaterialAccountingGroup.h"
00026 #include "TrackingMaterialAnalyser.h"
00027 #include "TrackingMaterialPlotter.h"
00028
00029
00030 TrackingMaterialAnalyser::TrackingMaterialAnalyser(const edm::ParameterSet& iPSet)
00031 {
00032 m_material = iPSet.getParameter<edm::InputTag>("MaterialAccounting");
00033 m_groupNames = iPSet.getParameter<std::vector<std::string> >("Groups");
00034 const std::string & splitmode = iPSet.getParameter<std::string>("SplitMode");
00035 if (strcasecmp(splitmode.c_str(), "NearestLayer") == 0) {
00036 m_splitMode = NEAREST_LAYER;
00037 } else if (strcasecmp(splitmode.c_str(), "InnerLayer") == 0) {
00038 m_splitMode = INNER_LAYER;
00039 } else if (strcasecmp(splitmode.c_str(), "OuterLayer") == 0) {
00040 m_splitMode = OUTER_LAYER;
00041 } else {
00042 m_splitMode = UNDEFINED;
00043 throw edm::Exception(edm::errors::LogicError) << "Invalid SplitMode \"" << splitmode << "\". Acceptable values are \"NearestLayer\", \"InnerLayer\", \"OuterLayer\".";
00044 }
00045 m_skipAfterLastDetector = iPSet.getParameter<bool>("SkipAfterLastDetector");
00046 m_skipBeforeFirstDetector = iPSet.getParameter<bool>("SkipBeforeFirstDetector");
00047 m_saveSummaryPlot = iPSet.getParameter<bool>("SaveSummaryPlot");
00048 m_saveDetailedPlots = iPSet.getParameter<bool>("SaveDetailedPlots");
00049 m_saveParameters = iPSet.getParameter<bool>("SaveParameters");
00050 m_saveXml = iPSet.getParameter<bool>("SaveXML");
00051 if (m_saveSummaryPlot)
00052 m_plotter = new TrackingMaterialPlotter( 300., 120., 10 );
00053 else
00054 m_plotter = NULL;
00055 }
00056
00057
00058 TrackingMaterialAnalyser::~TrackingMaterialAnalyser(void)
00059 {
00060 if (m_plotter)
00061 delete m_plotter;
00062 }
00063
00064
00065 void TrackingMaterialAnalyser::saveParameters(const char* name)
00066 {
00067 std::ofstream parameters(name);
00068 std::cout << std::endl;
00069 for (unsigned int i = 0; i < m_groups.size(); ++i) {
00070 MaterialAccountingGroup & layer = *(m_groups[i]);
00071 std::cout << layer.name() << std::endl;
00072 std::cout << boost::format("\tnumber of hits: %9d") % layer.tracks() << std::endl;
00073 std::cout << boost::format("\tnormalized segment length: %9.1f ± %9.1f cm") % layer.averageLength() % layer.sigmaLength() << std::endl;
00074 std::cout << boost::format("\tnormalized radiation lengths: %9.3f ± %9.3f") % layer.averageRadiationLengths() % layer.sigmaRadiationLengths() << std::endl;
00075 std::cout << boost::format("\tnormalized energy loss: %9.3f ± %9.3f MeV") % layer.averageEnergyLoss() % layer.sigmaEnergyLoss() << std::endl;
00076 parameters << boost::format("%-20s\t%7d\t%5.1f ± %5.1f cm\t%6.4f ± %6.4f \t%6.4fe-03 ± %6.4fe-03 GeV")
00077 % layer.name()
00078 % layer.tracks()
00079 % layer.averageLength() % layer.sigmaLength()
00080 % layer.averageRadiationLengths() % layer.sigmaRadiationLengths()
00081 % layer.averageEnergyLoss() % layer.sigmaEnergyLoss()
00082 << std::endl;
00083 }
00084 std::cout << std::endl;
00085
00086 parameters.close();
00087 }
00088
00089
00090 void TrackingMaterialAnalyser::saveXml(const char* name)
00091 {
00092 std::ofstream xml(name);
00093 xml << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl;
00094 xml << "<Groups>" << std::endl;
00095 for (unsigned int i = 0; i < m_groups.size(); ++i) {
00096 MaterialAccountingGroup & layer = *(m_groups[i]);
00097 xml << " <Group name=\"" << layer.name() << "\">\n"
00098 << " <Parameter name=\"TrackerRadLength\" value=\"" << layer.averageRadiationLengths() << "\"/>\n"
00099 << " <Parameter name=\"TrackerXi\" value=\"" << layer.averageEnergyLoss() << "\"/>\n"
00100 << " </Group>\n"
00101 << std::endl;
00102 }
00103 xml << "</Groups>" << std::endl;
00104 }
00105
00106
00107 void TrackingMaterialAnalyser::saveLayerPlots()
00108 {
00109 for (unsigned int i = 0; i < m_groups.size(); ++i) {
00110 MaterialAccountingGroup & layer = *(m_groups[i]);
00111 layer.savePlots();
00112 }
00113 }
00114
00115
00116 void TrackingMaterialAnalyser::endJob(void)
00117 {
00118 if (m_saveParameters)
00119 saveParameters("parameters");
00120
00121 if (m_saveXml)
00122 saveXml("parameters.xml");
00123
00124 if (m_saveDetailedPlots)
00125 saveLayerPlots();
00126
00127 if (m_saveSummaryPlot and m_plotter) {
00128 m_plotter->normalize();
00129 m_plotter->draw();
00130 }
00131 }
00132
00133
00134
00135
00136 void TrackingMaterialAnalyser::analyze(const edm::Event& event, const edm::EventSetup& setup)
00137 {
00138 edm::ESTransientHandle<DDCompactView> hDDD;
00139 setup.get<IdealGeometryRecord>().get( hDDD );
00140
00141 m_groups.reserve( m_groupNames.size() );
00142 for (unsigned int i = 0; i < m_groupNames.size(); ++i)
00143 m_groups.push_back( new MaterialAccountingGroup( m_groupNames[i], * hDDD) );
00144
00145
00146 std::cout << "TrackingMaterialAnalyser: List of the tracker groups: " << std::endl;
00147 for (unsigned int i = 0; i < m_groups.size(); ++i)
00148 std::cout << '\t' << m_groups[i]->info() << std::endl;
00149 std::cout << std::endl;
00150
00151 edm::Handle< std::vector<MaterialAccountingTrack> > h_tracks;
00152 event.getByLabel(m_material, h_tracks);
00153
00154 for (std::vector<MaterialAccountingTrack>::const_iterator t = h_tracks->begin(), end = h_tracks->end(); t != end; ++t) {
00155 MaterialAccountingTrack track(*t);
00156 split( track );
00157 }
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167 void TrackingMaterialAnalyser::split( MaterialAccountingTrack & track )
00168 {
00169
00170 std::vector<int> group( track.m_detectors.size() );
00171 for (unsigned int i = 0; i < track.m_detectors.size(); ++i)
00172 group[i] = findLayer( track.m_detectors[i] );
00173
00174 unsigned int detectors = track.m_detectors.size();
00175 if (detectors == 0) {
00176
00177
00178 if (m_plotter)
00179 for (unsigned int i = 1; i < track.m_steps.size(); ++i)
00180 m_plotter->plotSegmentUnassigned( track.m_steps[i] );
00181 } else {
00182 const double TOLERANCE = 0.0001;
00183 std::vector<double> limits(detectors + 2);
00184
00185
00186 if (m_skipBeforeFirstDetector)
00187 limits[0] = track.m_detectors[0].m_curvilinearIn - TOLERANCE;
00188 else
00189 limits[0] = - TOLERANCE;
00190 if (m_skipAfterLastDetector)
00191 limits[detectors] = track.m_detectors[detectors-1].m_curvilinearOut + TOLERANCE;
00192 else
00193 limits[detectors] = track.m_total.length() + TOLERANCE;
00194 limits[detectors+1] = INFINITY;
00195
00196
00197 switch (m_splitMode) {
00198
00199
00200 case NEAREST_LAYER:
00201 for (unsigned int i = 1; i < detectors; ++i)
00202 limits[i] = (track.m_detectors[i-1].m_curvilinearOut + track.m_detectors[i].m_curvilinearIn) / 2.;
00203 break;
00204
00205
00206
00207 case INNER_LAYER:
00208 for (unsigned int i = 1; i < detectors; ++i)
00209 limits[i] = track.m_detectors[i].m_curvilinearIn - TOLERANCE;
00210 break;
00211
00212
00213
00214 case OUTER_LAYER:
00215 for (unsigned int i = 1; i < detectors; ++i)
00216 limits[i] = track.m_detectors[i-1].m_curvilinearOut + TOLERANCE;
00217 break;
00218
00219 case UNDEFINED:
00220 default:
00221
00222 throw edm::Exception(edm::errors::LogicError) << "Invalid SplitMode";
00223 }
00224
00225
00226
00227
00228 double begin = 0.;
00229 double end = 0.;
00230 unsigned int i = 1;
00231
00232
00233
00234 while (end < limits[0]) {
00235 const MaterialAccountingStep & step = track.m_steps[i++];
00236 end = begin + step.length();
00237
00238
00239 if (m_plotter)
00240 m_plotter->plotSegmentUnassigned( step );
00241
00242 begin = end;
00243
00244 }
00245
00246
00247
00248
00249 if (begin < limits[0] and end > limits[0]) {
00250 const MaterialAccountingStep & step = track.m_steps[i++];
00251 end = begin + step.length();
00252
00253 double fraction = (limits[0] - begin) / (end - begin);
00254 std::pair<MaterialAccountingStep, MaterialAccountingStep> parts = step.split(fraction);
00255
00256
00257 track.m_detectors[0].account( parts.second, limits[1], end );
00258
00259 if (m_plotter) {
00260
00261 m_plotter->plotSegmentUnassigned( parts.first );
00262
00263
00264 m_plotter->plotSegmentInLayer( parts.second, group[0] );
00265 }
00266 begin = end;
00267 }
00268
00269 unsigned int index = 0;
00270 while (i < track.m_steps.size()) {
00271 const MaterialAccountingStep & step = track.m_steps[i++];
00272
00273 end = begin + step.length();
00274
00275 if (begin > limits[detectors]) {
00276
00277 if (m_plotter)
00278 m_plotter->plotSegmentUnassigned( step );
00279 begin = end;
00280 continue;
00281 }
00282
00283
00284
00285
00286
00287 if (begin < limits[index] or end > limits[index+2]) {
00288
00289 std::cerr << "MaterialAccountingTrack::split(): ERROR: internal logic error, expected " << limits[index] << " < " << begin << " < " << limits[index+1] << std::endl;
00290 break;
00291 }
00292
00293
00294 if (limits[index] <= begin and end <= limits[index+1]) {
00295
00296 track.m_detectors[index].account( step, begin, end );
00297 if (m_plotter)
00298 m_plotter->plotSegmentInLayer( step, group[index] );
00299 } else {
00300
00301 double fraction = (limits[index+1] - begin) / (end - begin);
00302 std::pair<MaterialAccountingStep, MaterialAccountingStep> parts = step.split(fraction);
00303
00304 if (m_plotter) {
00305 if (index > 0)
00306 m_plotter->plotSegmentInLayer( parts.first, group[index] );
00307 else
00308
00309 m_plotter->plotSegmentUnassigned( parts.first );
00310
00311 if (index+1 < detectors)
00312 m_plotter->plotSegmentInLayer( parts.second, group[index+1] );
00313 else
00314
00315 m_plotter->plotSegmentUnassigned( parts.second );
00316 }
00317
00318 track.m_detectors[index].account( parts.first, begin, limits[index+1] );
00319 ++index;
00320
00321
00322 if (index < detectors)
00323 track.m_detectors[index].account( parts.second, limits[index+1], end );
00324 }
00325 begin = end;
00326 }
00327
00328 }
00329
00330
00331
00332 for (unsigned int i = 0; i < track.m_detectors.size(); ++i)
00333 if (group[i] != 0)
00334 m_groups[group[i]-1]->addDetector( track.m_detectors[i] );
00335
00336
00337 for (unsigned int i = 0; i < m_groups.size(); ++i)
00338 m_groups[i]->endOfTrack();
00339 }
00340
00341
00342
00343 int TrackingMaterialAnalyser::findLayer( const MaterialAccountingDetector & detector )
00344 {
00345 int index = 0;
00346 size_t inside = 0;
00347 for (size_t i = 0; i < m_groups.size(); ++i)
00348 if (m_groups[i]->inside(detector)) {
00349 ++inside;
00350 index = i+1;
00351 }
00352 if (inside == 0) {
00353 index = 0;
00354 std::cerr << "TrackingMaterialAnalyser::findLayer(...): ERROR: detector does not belong to any DetLayer" << std::endl;
00355 std::cerr << "TrackingMaterialAnalyser::findLayer(...): detector position: " << std::fixed
00356 << " (r: " << std::setprecision(1) << std::setw(5) << detector.position().perp()
00357 << ", z: " << std::setprecision(1) << std::setw(6) << detector.position().z()
00358 << ", phi: " << std::setprecision(3) << std::setw(6) << detector.position().phi() << ")"
00359 << std::endl;
00360 }
00361 if (inside > 1) {
00362 index = 0;
00363 std::cerr << "TrackingMaterialAnalyser::findLayer(...): ERROR: detector belongs to " << inside << "DetLayers" << std::endl;
00364 std::cerr << "TrackingMaterialAnalyser::findLayer(...): detector position: " << std::fixed
00365 << " (r: " << std::setprecision(1) << std::setw(5) << detector.position().perp()
00366 << ", z: " << std::setprecision(1) << std::setw(6) << detector.position().z()
00367 << ", phi: " << std::setprecision(3) << std::setw(6) << detector.position().phi() << ")"
00368 << std::endl;
00369 }
00370
00371 return index;
00372 }
00373
00374
00375
00376 #include "FWCore/PluginManager/interface/ModuleDef.h"
00377 #include "FWCore/Framework/interface/MakerMacros.h"
00378 DEFINE_FWK_MODULE(TrackingMaterialAnalyser);