00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <DQM/DTMonitorClient/src/DTOccupancyTest.h>
00013 #include <DQM/DTMonitorClient/src/DTOccupancyClusterBuilder.h>
00014
00015 #include "FWCore/ServiceRegistry/interface/Service.h"
00016 #include "FWCore/Framework/interface/LuminosityBlock.h"
00017 #include "FWCore/Framework/interface/EventSetup.h"
00018 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00019 #include "Geometry/Records/interface/MuonGeometryRecord.h"
00020 #include "Geometry/DTGeometry/interface/DTGeometry.h"
00021 #include "DQMServices/Core/interface/DQMStore.h"
00022 #include "DQMServices/Core/interface/MonitorElement.h"
00023 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00024
00025 #include "TMath.h"
00026
00027 using namespace edm;
00028 using namespace std;
00029
00030
00031
00032
00033 DTOccupancyTest::DTOccupancyTest(const edm::ParameterSet& ps){
00034 LogVerbatim ("DTDQM|DTMonitorClient|DTOccupancyTest") << "[DTOccupancyTest]: Constructor";
00035
00036
00037 dbe = Service<DQMStore>().operator->();
00038
00039 lsCounter = 0;
00040
00041 writeRootFile = ps.getUntrackedParameter<bool>("writeRootFile", false);
00042 if(writeRootFile) {
00043 rootFile = new TFile("DTOccupancyTest.root","RECREATE");
00044 ntuple = new TNtuple("OccupancyNtuple", "OccupancyNtuple", "ls:wh:st:se:lay1MeanCell:lay1RMS:lay2MeanCell:lay2RMS:lay3MeanCell:lay3RMS:lay4MeanCell:lay4RMS:lay5MeanCell:lay5RMS:lay6MeanCell:lay6RMS:lay7MeanCell:lay7RMS:lay8MeanCell:lay8RMS:lay9MeanCell:lay9RMS:lay10MeanCell:lay10RMS:lay11MeanCell:lay11RMS:lay12MeanCell:lay12RMS");
00045 }
00046
00047
00048 tpMode = ps.getUntrackedParameter<bool>("testPulseMode", false);
00049
00050 runOnAllHitsOccupancies = ps.getUntrackedParameter<bool>("runOnAllHitsOccupancies", true);
00051 runOnNoiseOccupancies = ps.getUntrackedParameter<bool>("runOnNoiseOccupancies", false);
00052 runOnInTimeOccupancies = ps.getUntrackedParameter<bool>("runOnInTimeOccupancies", false);
00053
00054 }
00055
00056
00057
00058
00059 DTOccupancyTest::~DTOccupancyTest(){
00060 LogVerbatim ("DTDQM|DTMonitorClient|DTOccupancyTest") << " destructor called" << endl;
00061
00062
00063 }
00064
00065
00066
00067
00068 void DTOccupancyTest::beginJob(){
00069 LogVerbatim ("DTDQM|DTMonitorClient|DTOccupancyTest") << "[DTOccupancyTest]: BeginJob";
00070
00071
00072 nevents = 0;
00073
00074
00075
00076 for(int wh = -2; wh <= 2; ++wh) {
00077 bookHistos(wh, string("Occupancies"), "OccupancySummary");
00078 }
00079
00080 dbe->setCurrentFolder(topFolder());
00081 string title = "Occupancy Summary";
00082 if(tpMode) {
00083 title = "Test Pulse Occupancy Summary";
00084 }
00085
00086 summaryHisto = dbe->book2D("OccupancySummary",title.c_str(),12,1,13,5,-2,3);
00087 summaryHisto->setAxisTitle("sector",1);
00088 summaryHisto->setAxisTitle("wheel",2);
00089
00090
00091 glbSummaryHisto = dbe->book2D("OccupancyGlbSummary",title.c_str(),12,1,13,5,-2,3);
00092 glbSummaryHisto->setAxisTitle("sector",1);
00093 glbSummaryHisto->setAxisTitle("wheel",2);
00094
00095
00096
00097 if(runOnAllHitsOccupancies) {
00098 nameMonitoredHisto = "OccupancyAllHits_perCh";
00099 } else if(runOnNoiseOccupancies) {
00100 nameMonitoredHisto = "OccupancyNoise_perCh";
00101 } else if(runOnInTimeOccupancies) {
00102 nameMonitoredHisto = "OccupancyInTimeHits_perCh";
00103 } else {
00104 nameMonitoredHisto = "OccupancyAllHits_perCh";
00105 }
00106
00107 }
00108
00109
00110
00111
00112 void DTOccupancyTest::beginRun(const edm::Run& run, const EventSetup& context){
00113
00114 LogVerbatim ("DTDQM|DTMonitorClient|DTOccupancyTest") << "[DTOccupancyTest]: BeginRun";
00115
00116
00117 context.get<MuonGeometryRecord>().get(muonGeom);
00118
00119 }
00120
00121
00122
00123
00124 void DTOccupancyTest::beginLuminosityBlock(LuminosityBlock const& lumiSeg, EventSetup const& context) {
00125 LogVerbatim ("DTDQM|DTMonitorClient|DTOccupancyTest") <<"[DTOccupancyTest]: Begin of LS transition";
00126 }
00127
00128
00129
00130
00131 void DTOccupancyTest::analyze(const Event& e, const EventSetup& context) {
00132 nevents++;
00133
00134
00135 }
00136
00137
00138
00139
00140 void DTOccupancyTest::endLuminosityBlock(LuminosityBlock const& lumiSeg, EventSetup const& context) {
00141 LogVerbatim ("DTDQM|DTMonitorClient|DTOccupancyTest")
00142 <<"[DTOccupancyTest]: End of LS transition, performing the DQM client operation";
00143 lsCounter++;
00144
00145
00146
00147
00148 summaryHisto->Reset();
00149 glbSummaryHisto->Reset();
00150
00151
00152 vector<DTChamber*> chambers = muonGeom->chambers();
00153
00154 for(vector<DTChamber*>::const_iterator chamber = chambers.begin();
00155 chamber != chambers.end(); ++chamber) {
00156 DTChamberId chId = (*chamber)->id();
00157
00158 MonitorElement * chamberOccupancyHisto = dbe->get(getMEName(nameMonitoredHisto, chId));
00159
00160
00161 if(chamberOccupancyHisto != 0) {
00162
00163 TH2F* histo = chamberOccupancyHisto->getTH2F();
00164 float chamberPercentage = 1.;
00165 int result = runOccupancyTest(histo, chId, chamberPercentage);
00166 int sector = chId.sector();
00167
00168 if(sector == 13) {
00169 sector = 4;
00170 float resultSect4 = wheelHistos[chId.wheel()]->getBinContent(sector, chId.station());
00171 if(resultSect4 > result) {
00172 result = (int)resultSect4;
00173 }
00174 } else if(sector == 14) {
00175 sector = 10;
00176 float resultSect10 = wheelHistos[chId.wheel()]->getBinContent(sector, chId.station());
00177 if(resultSect10 > result) {
00178 result = (int)resultSect10;
00179 }
00180 }
00181
00182
00183 if((sector == 4 || sector == 10) && chId.station() == 4)
00184 chamberPercentage = chamberPercentage/2.;
00185
00186 wheelHistos[chId.wheel()]->setBinContent(sector, chId.station(),result);
00187 if(result > summaryHisto->getBinContent(sector, chId.wheel()+3)) {
00188 summaryHisto->setBinContent(sector, chId.wheel()+3, result);
00189 }
00190 glbSummaryHisto->Fill(sector, chId.wheel(), chamberPercentage*1./4.);
00191 } else {
00192 LogVerbatim ("DTDQM|DTMonitorClient|DTOccupancyTest") << "[DTOccupancyTest] ME: "
00193 << getMEName(nameMonitoredHisto, chId) << " not found!" << endl;
00194 }
00195
00196 }
00197
00198
00199
00200
00201
00202 if(writeRootFile) ntuple->AutoSave("SaveSelf");
00203
00204 }
00205
00206
00207 void DTOccupancyTest::endJob(){
00208
00209 LogVerbatim ("DTDQM|DTMonitorClient|DTOccupancyTest") << "[DTOccupancyTest] endjob called!";
00210 if(writeRootFile) {
00211 rootFile->cd();
00212 ntuple->Write();
00213 rootFile->Close();
00214 }
00215 }
00216
00217
00218
00219
00220 void DTOccupancyTest::bookHistos(const int wheelId, string folder, string histoTag) {
00221
00222 stringstream wheel; wheel << wheelId;
00223 dbe->setCurrentFolder(topFolder());
00224
00225
00226 string histoName = histoTag + "_W" + wheel.str();
00227
00228
00229 LogVerbatim ("DTDQM|DTMonitorClient|DTOccupancyTest") <<"[DTOccupancyTest]: booking wheel histo:"
00230 << histoName
00231 << " (tag "
00232 << histoTag
00233 << ") in: "
00234 << topFolder() + "Wheel"+ wheel.str() + "/" + folder << endl;
00235
00236 string histoTitle = "Occupancy summary WHEEL: "+wheel.str();
00237 if(tpMode) {
00238 histoTitle = "TP Occupancy summary WHEEL: "+wheel.str();
00239 }
00240 wheelHistos[wheelId] = dbe->book2D(histoName,histoTitle,12,1,13,4,1,5);
00241 wheelHistos[wheelId]->setBinLabel(1,"MB1",2);
00242 wheelHistos[wheelId]->setBinLabel(2,"MB2",2);
00243 wheelHistos[wheelId]->setBinLabel(3,"MB3",2);
00244 wheelHistos[wheelId]->setBinLabel(4,"MB4",2);
00245 wheelHistos[wheelId]->setAxisTitle("sector",1);
00246 }
00247
00248
00249
00250 string DTOccupancyTest::getMEName(string histoTag, const DTChamberId& chId) {
00251
00252 stringstream wheel; wheel << chId.wheel();
00253 stringstream station; station << chId.station();
00254 stringstream sector; sector << chId.sector();
00255
00256
00257 string folderRoot = topFolder() + "Wheel" + wheel.str() +
00258 "/Sector" + sector.str() +
00259 "/Station" + station.str() + "/";
00260
00261 string folder = "Occupancies/";
00262
00263
00264 string histoName = histoTag
00265 + "_W" + wheel.str()
00266 + "_St" + station.str()
00267 + "_Sec" + sector.str();
00268
00269 string histoname = folderRoot + histoName;
00270
00271 return histoname;
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 int DTOccupancyTest::runOccupancyTest(TH2F *histo, const DTChamberId& chId,
00285 float& chamberPercentage) {
00286 int nBinsX = histo->GetNbinsX();
00287
00288
00289 bool failSL = false;
00290 bool failLayer = false;
00291 bool failCells = false;
00292
00293
00294 if(histo->Integral() == 0) {
00295 chamberPercentage = 0;
00296 return 4;
00297 }
00298
00299 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << "--- Occupancy test for chamber: " << chId << endl;
00300
00301 int nSL = 3;
00302 if(chId.station() == 4) nSL = 2;
00303
00304
00305 float values[28];
00306 if(writeRootFile) {
00307 values[0] = lsCounter;
00308 values[1] = chId.wheel();
00309 values[2] = chId.station();
00310 values[3] = chId.sector();
00311 }
00312
00313
00314
00315
00316 double totalChamberOccupp = 0;
00317 double squaredLayerOccupSum = 0;
00318
00319 map<DTLayerId, pair<double, double> > averageCellOccupAndRMS;
00320 map<DTLayerId, double> layerOccupancyMap;
00321
00322 int index = 3;
00323 for(int slay = 1; slay <= 3; ++slay) {
00324
00325 if(chId.station() == 4 && slay == 2) {
00326 if(writeRootFile) {
00327 values[12] = -1;
00328 values[13] = -1;
00329 values[14] = -1;
00330 values[15] = -1;
00331 values[16] = -1;
00332 values[17] = -1;
00333 values[18] = -1;
00334 values[19] = -1;
00335 }
00336 index = 19;
00337 continue;
00338 }
00339
00340 int binYlow = ((slay-1)*4)+1;
00341 int binYhigh = binYlow+3;
00342 double slInteg = histo->Integral(1,nBinsX,binYlow,binYhigh);
00343 if(slInteg == 0) {
00344 chamberPercentage = 1.-1./(float)nSL;
00345 return 3;
00346 }
00347
00348 for(int lay = 1; lay <= 4; ++lay) {
00349 DTLayerId layID(chId,slay,lay);
00350
00351 int binY = binYlow+(lay-1);
00352
00353 double layerInteg = histo->Integral(1,nBinsX,binY,binY);
00354 squaredLayerOccupSum += layerInteg*layerInteg;
00355 totalChamberOccupp+= layerInteg;
00356
00357 layerOccupancyMap[layID] = layerInteg;
00358
00359
00360 int nWires = muonGeom->layer(layID)->specificTopology().channels();
00361 int firstWire = muonGeom->layer(layID)->specificTopology().firstChannel();
00362 double layerSquaredSum = 0;
00363
00364 histo->SetBinContent(nBinsX+1,binY,0.);
00365
00366 for(int cell = firstWire; cell != (nWires+firstWire); ++cell) {
00367 double cellOccup = histo->GetBinContent(cell,binY);
00368 layerSquaredSum+=cellOccup*cellOccup;
00369 }
00370
00371
00372
00373
00374 double averageCellOccup = layerInteg/nWires;
00375 double averageSquaredCellOccup = layerSquaredSum/nWires;
00376 double rmsCellOccup = sqrt(averageSquaredCellOccup - averageCellOccup*averageCellOccup);
00377 averageCellOccupAndRMS[layID] = make_pair(averageCellOccup, rmsCellOccup);
00378 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " " << layID
00379 << " average cell occ.: " << averageCellOccup
00380 << " RMS: " << rmsCellOccup << endl;
00381 if(writeRootFile) {
00382 index++;
00383 values[index] = averageCellOccup;
00384 index++;
00385 values[index] = rmsCellOccup;
00386 }
00387 }
00388 }
00389
00390
00391 if(writeRootFile) ntuple->Fill(values);
00392
00393
00394
00395
00396
00397 double minCellRMS = 99999999;
00398 double referenceCellOccup = -1;
00399
00400 DTOccupancyClusterBuilder builder;
00401
00402
00403 for(map<DTLayerId, pair<double, double> >::const_iterator layAndValues = averageCellOccupAndRMS.begin();
00404 layAndValues != averageCellOccupAndRMS.end(); layAndValues++) {
00405 DTLayerId lid = (*layAndValues).first;
00406
00407 double rms = (*layAndValues).second.second;
00408 double lOcc = layerOccupancyMap[lid];
00409 double avCellOcc = (*layAndValues).second.first;
00410 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " " << lid << " tot. occ: " << lOcc
00411 << " average cell occ: " << avCellOcc
00412 << " RMS: " << rms << endl;
00413
00414 if(avCellOcc != 0) {
00415 DTOccupancyPoint point(avCellOcc, rms, lid);
00416 builder.addPoint(point);
00417 } else {
00418 if(monitoredLayers.find(lid) == monitoredLayers.end()) monitoredLayers.insert(lid);
00419 }
00420 }
00421
00422 builder.buildClusters();
00423 referenceCellOccup = builder.getBestCluster().averageMean();
00424 minCellRMS = builder.getBestCluster().averageRMS();
00425
00426
00427
00428 double safeFactor = 3.;
00429
00430
00431 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " Reference cell occup.: " << referenceCellOccup
00432 << " RMS: " << minCellRMS << endl;
00433
00434
00435
00436
00437
00438
00439
00440
00441 int nFailingSLs = 0;
00442
00443
00444 for(int slay = 1; slay <= 3; ++slay) {
00445
00446 if(chId.station() == 4 && slay == 2) continue;
00447
00448 int binYlow = ((slay-1)*4)+1;
00449
00450
00451
00452 int nFailingLayers = 0;
00453
00454 for(int lay = 1; lay <= 4; ++lay) {
00455 DTLayerId layID(chId,slay,lay);
00456 int nWires = muonGeom->layer(layID)->specificTopology().channels();
00457 int firstWire = muonGeom->layer(layID)->specificTopology().firstChannel();
00458 int binY = binYlow+(lay-1);
00459
00460
00461 double layerInteg = histo->Integral(1,nBinsX,binY,binY);
00462
00463 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " layer: " << layID << " integral: " << layerInteg << endl;
00464
00465
00466 bool alreadyMonitored = false;
00467 if(monitoredLayers.find(layID) != monitoredLayers.end()) alreadyMonitored = true;
00468
00469
00470 if(layerInteg == 0) {
00471 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " fail layer: no entries" << endl;
00472
00473 if(!alreadyMonitored) monitoredLayers.insert(layID);
00474 nFailingLayers++;
00475 failLayer = true;
00476 histo->SetBinContent(nBinsX+1,binY,-1.);
00477
00478 continue;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 if(alreadyMonitored || builder.isProblematic(layID)) {
00492
00493
00494 if(monitoredLayers.find(layID) == monitoredLayers.end()) monitoredLayers.insert(layID);
00495
00496
00497 int totalDeadCells = 0;
00498 int nDeadCellsInARow = 1;
00499 int nDeadCellsInARowMax = 0;
00500 int nCellsZeroCount = 0;
00501 bool previousIsDead = false;
00502
00503 int interDeadCells = 0;
00504 for(int cell = firstWire; cell != (nWires+firstWire); ++cell) {
00505 double cellOccup = histo->GetBinContent(cell,binY);
00506 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " cell occup: " << cellOccup;
00507 if(cellOccup == 0 || cellOccup < (referenceCellOccup-safeFactor*sqrt(referenceCellOccup))) {
00508 if(cellOccup == 0) nCellsZeroCount++;
00509 totalDeadCells++;
00510 if(previousIsDead) nDeadCellsInARow++;
00511 previousIsDead = true;
00512 interDeadCells = 0;
00513 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " below reference" << endl;
00514 } else {
00515 previousIsDead = false;
00516 interDeadCells++;
00517
00518
00519 if(interDeadCells > 3) {
00520 if(nDeadCellsInARow > nDeadCellsInARowMax) nDeadCellsInARowMax = nDeadCellsInARow;
00521 nDeadCellsInARow = 1;
00522 }
00523 }
00524 }
00525 if(nDeadCellsInARow > nDeadCellsInARowMax) nDeadCellsInARowMax = nDeadCellsInARow;
00526 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " # wires: " << nWires
00527 << " # cells 0 count: " << nCellsZeroCount
00528 << " # dead cells in a row: " << nDeadCellsInARowMax
00529 << " total # of dead cells: " << totalDeadCells;
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 if((TMath::Erfc(referenceCellOccup/sqrt(referenceCellOccup)) < 10./(double)nWires &&
00542 nDeadCellsInARowMax>= 10.) ||
00543 (TMath::Erfc(referenceCellOccup/sqrt(referenceCellOccup)) < 0.5 &&
00544 totalDeadCells > nWires/2.)) {
00545 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " -> fail layer!" << endl;
00546 nFailingLayers++;
00547 failLayer = true;
00548 histo->SetBinContent(nBinsX+1,binY,-1.);
00549 } else if(referenceCellOccup > 10 &&
00550 nCellsZeroCount > nWires/3. &&
00551 (double)nCellsZeroCount/(double)nWires >
00552 2.*TMath::Erfc(referenceCellOccup/sqrt(referenceCellOccup))) {
00553 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " -> would fail cells!" << endl;
00554 LogTrace("DTDQM|DTMonitorClient|DTOccupancyTest") << " # of cells with 0 count: " << nCellsZeroCount
00555 << " # wires: " << nWires
00556 << " erfc: "
00557 << TMath::Erfc(referenceCellOccup/sqrt(referenceCellOccup))
00558 << endl;
00559
00560
00561 }
00562
00563
00564
00565
00566
00567
00568
00569 }
00570 }
00571
00572 if( nFailingLayers == 4) {
00573 nFailingSLs++;
00574 failSL = true;
00575 }
00576 }
00577
00578
00579 if(nFailingSLs == nSL) {
00580 chamberPercentage = 0;
00581 return 4;
00582 } else {
00583 chamberPercentage = 1.-(float)nFailingSLs/(float)nSL;
00584 }
00585
00586
00587 if(failSL) return 3;
00588 if(failLayer) return 2;
00589 if(failCells) return 1;
00590
00591 return 0;
00592 }
00593
00594
00595 string DTOccupancyTest::topFolder() const {
00596 if(tpMode) return string("DT/10-TestPulses/");
00597 return string("DT/01-Digi/");
00598 }