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