00001 #include <iostream>
00002 #include <cmath>
00003 #include <cassert>
00004 #include <algorithm>
00005 #include <functional>
00006
00007 #include "TRandom2.h"
00008
00009 #include "MapsSensor.hh"
00010 #include "ToString.h"
00011
00012
00013 struct IlEstMort :
00014 public std::binary_function<const MapsSensor*, const MapsSensor::physXY, bool > {
00015 bool operator()(const MapsSensor* s, const MapsSensor::physXY p) const {
00016 return s->isDeadArea(p);
00017 }
00018 };
00019
00020 MapsSensor::~MapsSensor() {
00021 }
00022
00023 MapsSensor::physXY MapsSensor::getAlignment() const {
00024 return myAlignment;
00025 }
00026
00027 void MapsSensor::setAlignment(MapsSensor::physXY alignment) {
00028 myAlignment = alignment;
00029 }
00030
00031 void MapsSensor::registerTrackConfirm(unsigned threshold,
00032 MapsSensor::coord place, unsigned bx) {
00033 if (myHitsByThreshold.count(threshold) == 0) {
00034 myKnownThresholds.push_back(threshold);
00035 std::pair<unsigned, unsigned>* hits =
00036 new std::pair<unsigned, unsigned>(0, 0);
00037 std::pair<unsigned, unsigned>* samplerHits =
00038 new std::pair<unsigned, unsigned>(0, 0);
00039 std::pair<unsigned, unsigned>* shaperHits =
00040 new std::pair<unsigned, unsigned>(0, 0);
00041
00042 myHitsByThreshold[threshold] = hits;
00043 mySamplerHitsByThreshold[threshold] = samplerHits;
00044 myShaperHitsByThreshold[threshold] = shaperHits;
00045 }
00046
00047 if (myTimes.count(bx) == 0) {
00048 myTimes[bx] = new std::pair<unsigned, unsigned>(0, 0);
00049 }
00050
00051 std::pair<unsigned, unsigned>* hits = myHitsByThreshold[threshold];
00052 std::pair<unsigned, unsigned>* times = myTimes[bx];
00053
00054 (*hits).first++;
00055 (*times).first++;
00056
00057 if (place.first < 84) {
00058
00059 std::pair<unsigned, unsigned>* shaperHits =
00060 myShaperHitsByThreshold[threshold];
00061 (*shaperHits).first++;
00062 } else {
00063
00064 std::pair<unsigned, unsigned>* samplerHits =
00065 mySamplerHitsByThreshold[threshold];
00066 (*samplerHits).first++;
00067 }
00068 myEfficientHits.push_back(place);
00069 }
00070
00071 void MapsSensor::registerTrackConfirm(unsigned threshold,
00072 MapsSensor::coord place, unsigned bx, MapsSensor::physXY resid) {
00073 myFourthHitResids.push_back(resid);
00074 registerTrackConfirm(threshold, place, bx);
00075 }
00076 void MapsSensor::registerTrackMiss(unsigned threshold, unsigned bx) {
00077 if (myHitsByThreshold.count(threshold) == 0) {
00078 myKnownThresholds.push_back(threshold);
00079 std::pair<unsigned, unsigned>* hits =
00080 new std::pair<unsigned, unsigned>(0, 0);
00081 myHitsByThreshold[threshold] = hits;
00082
00083 std::pair<unsigned, unsigned>* shaperHits =
00084 new std::pair<unsigned, unsigned>(0, 0);
00085 myShaperHitsByThreshold[threshold] = shaperHits;
00086
00087 std::pair<unsigned, unsigned>* samplerHits =
00088 new std::pair<unsigned, unsigned>(0, 0);
00089 mySamplerHitsByThreshold[threshold] = samplerHits;
00090 }
00091 if (myTimes.count(bx) == 0) {
00092 myTimes[bx] = new std::pair<unsigned, unsigned>(0, 0);
00093 }
00094 std::pair<unsigned, unsigned>* hits = myHitsByThreshold[threshold];
00095 std::pair<unsigned, unsigned>* times = myTimes[bx];
00096
00097 (*hits).second++;
00098 (*times).second++;
00099 }
00100
00101 void MapsSensor::registerTrackMiss(unsigned threshold, MapsSensor::coord pred,
00102 unsigned bx) {
00103 myInefficientHits.push_back(pred);
00104 registerTrackMiss(threshold, bx);
00105 if (pred.first < 84) {
00106
00107 std::pair<unsigned, unsigned>* shaperHits =
00108 myShaperHitsByThreshold[threshold];
00109 (*shaperHits).second++;
00110 } else {
00111
00112 std::pair<unsigned, unsigned>* samplerHits =
00113 mySamplerHitsByThreshold[threshold];
00114 (*samplerHits).second++;
00115 }
00116 physXY predPlace;
00117 convertHitToPhysical(pred, predPlace);
00118 malign(predPlace);
00119 rotateGlobalToLocal(predPlace);
00120 myInefficientPlaces.push_back(predPlace);
00121 }
00122
00123 void MapsSensor::registerTrackMiss(unsigned threshold, MapsSensor::physXY pred,
00124 unsigned bx) {
00125 myInefficientPlaces.push_back(pred);
00126 registerTrackMiss(threshold, bx);
00127 malign(pred);
00128 rotateGlobalToLocal(pred);
00129 coord predHit;
00130 if (!isDeadArea(pred)) {
00131 convertPhysicalToHit(pred, predHit);
00132 myInefficientHits.push_back(predHit);
00133 if (predHit.first < 84) {
00134
00135 std::pair<unsigned, unsigned>* shaperHits =
00136 myShaperHitsByThreshold[threshold];
00137 (*shaperHits).second++;
00138 } else {
00139
00140 std::pair<unsigned, unsigned>* samplerHits =
00141 mySamplerHitsByThreshold[threshold];
00142 (*samplerHits).second++;
00143 }
00144 }
00145 }
00146
00147 void MapsSensor::registerGeneralHit(unsigned threshold,
00148 MapsSensor::coord place, unsigned bx) {
00149 myGeneralHits.push_back(place);
00150 std::cout<< "WARNING: " << __PRETTY_FUNCTION__
00151 << " not yet fully implemented!!!\n";
00152
00153 }
00154 double MapsSensor::getEfficiency(unsigned threshold, bool withShapers,
00155 bool withSamplers) {
00156 if (myHitsByThreshold.count(threshold) == 0)
00157 return -1.0;
00158 std::pair<unsigned, unsigned>* hits;
00159
00160 if (withShapers && withSamplers)
00161 hits = myHitsByThreshold[threshold];
00162 else if (withShapers && !withSamplers)
00163 hits = myShaperHitsByThreshold[threshold];
00164 else if (withSamplers && !withShapers)
00165 hits = mySamplerHitsByThreshold[threshold];
00166 else {
00167 MapsException* me = new MapsException("Efficiency calculation called for no active area!");
00168 throw me;
00169 }
00170 return static_cast<double>((*hits).first) / ((*hits).first + (*hits).second);
00171 }
00172
00173 void MapsSensor::getInefficiencyXYPlot(TH2F& plot, bool physicalXY) {
00174 if (!physicalXY) {
00175 plot.SetTitle(("XY inefficiency for sensor " + toString(myId)).c_str());
00176 plot.SetName(("hXYinefficiencySensor" + toString(myId)).c_str());
00177 plot.SetBins(168, 0, 168, 168, 0, 168);
00178 plot.SetXTitle("x pixel");
00179 plot.SetYTitle("y pixel");
00180
00181 for (std::vector<MapsSensor::coord>::const_iterator it =
00182 myInefficientHits.begin(); it != myInefficientHits.end(); it++) {
00183 plot.Fill((*it).first, (*it).second);
00184 }
00185 } else {
00186 plot.SetTitle(("XY inefficiency for sensor " + toString(myId)).c_str());
00187 plot.SetName(("hXYinefficiencySensor" + toString(myId)).c_str());
00188 plot.SetBins(1000, -5.0, 5.0, 1000, -5.0, 5.0);
00189 plot.SetXTitle("x (mm)");
00190 plot.SetYTitle("y (mm)");
00191
00192 for (std::vector<MapsSensor::physXY>::const_iterator it =
00193 myInefficientPlaces.begin(); it != myInefficientPlaces.end(); it++) {
00194 plot.Fill((*it).first, (*it).second);
00195 }
00196 }
00197 }
00198 void MapsSensor::getEfficiencyXYPlot(TH2F& plot) {
00199 plot.SetTitle(("XY efficiency for sensor " + toString(myId)).c_str());
00200 plot.SetName(("hXYefficiencySensor" + toString(myId)).c_str());
00201 plot.SetBins(168, 0, 168, 168, 0, 168);
00202 plot.SetXTitle("x pixel");
00203 plot.SetYTitle("y pixel");
00204
00205 for (std::vector<MapsSensor::coord>::const_iterator it =
00206 myEfficientHits.begin(); it != myEfficientHits.end(); it++) {
00207
00208 plot.Fill((*it).first, (*it).second);
00209 }
00210 }
00211 void MapsSensor::getFourthHitResidualPlot(TH2F& plot) {
00212 plot.SetTitle(("R_{4} for 3 hit track w/alignment, sensor " + toString(myId)).c_str());
00213 plot.SetName(("hXYfourthHitResidSensor" + toString(myId)).c_str());
00214 plot.SetBins(100, -1.0, 1.0, 100, -1.0, 1.0);
00215 plot.SetXTitle("x pixel residual");
00216 plot.SetYTitle("y pixel residual");
00217
00218 for (std::vector<MapsSensor::physXY>::const_iterator it =
00219 myFourthHitResids.begin(); it != myFourthHitResids.end(); it++) {
00220
00221
00222
00223 plot.Fill((*it).first, (*it).second);
00224 }
00225
00226 }
00227 void MapsSensor::getEfficiencyTimestamps(TH1F& plot) {
00228 plot.SetName(("hTimestampsEfficiencySensor"+ toString(myId)).c_str());
00229 plot.SetTitle(("Efficiency timestamps for sensor " + toString(myId)).c_str());
00230 plot.SetBins(128, 0, 8192);
00231 plot.SetYTitle("Entries/64");
00232 plot.SetXTitle("Time");
00233
00234 for (unsigned t(0); t < 8192; t++) {
00235 if (myTimes.count(t) != 0) {
00236 std::pair<unsigned, unsigned>* count = myTimes[t];
00237 plot.Fill(t, (*count).first);
00238 }
00239 }
00240 }
00241
00242 void MapsSensor::getInefficiencyTimestamps(TH1F& plot) {
00243 plot.SetName(("hTimestampsInefficiencySensor"+ toString(myId)).c_str());
00244 plot.SetTitle(("Inefficiency timestamps for sensor " + toString(myId)).c_str());
00245 plot.SetBins(128, 0, 8192);
00246 plot.SetYTitle("Entries/64");
00247 plot.SetXTitle("Time");
00248
00249 for (unsigned t(0); t < 8192; t++) {
00250 if (myTimes.count(t) != 0) {
00251 std::pair<unsigned, unsigned>* count = myTimes[t];
00252 plot.Fill(t, (*count).second);
00253 }
00254 }
00255 }
00256
00257 void MapsSensor::getResidualXYPlot(TH2F& plot) const {
00258 plot.SetName(("hResidualsSensor" + toString(myId)).c_str());
00259 plot.SetTitle(("Residuals for sensor " + toString(myId)).c_str());
00260 plot.SetXTitle("x residual (mm)");
00261 plot.SetYTitle("y residual (mm)");
00262 plot.SetBins(100, -1.0, 1.0, 100, -1.0, 1.0);
00263 for (std::vector<std::pair<double, double> >::const_iterator it =
00264 myResiduals.begin(); it != myResiduals.end(); it++) {
00265 plot.Fill((*it).first, (*it).second);
00266 }
00267 }
00268
00269 void MapsSensor::getEfficiencyCurve(TH1F& plot, int bins, int low, int high,
00270 bool withShapers, bool withSamplers) {
00271 if (withShapers && !withSamplers) {
00272 plot.SetTitle(("Shaper efficiency for sensor " + toString(myId)).c_str());
00273 plot.SetName(("hShaperEfficiencySensor" + toString(myId)).c_str());
00274 } else if (withSamplers && !withShapers) {
00275 plot.SetTitle(("Sampler efficiency for sensor " + toString(myId)).c_str());
00276 plot.SetName(("hSamplerEfficiencySensor" + toString(myId)).c_str());
00277 } else if (withShapers && withSamplers) {
00278 plot.SetTitle(("Efficiency for sensor " + toString(myId)).c_str());
00279 plot.SetName(("hEfficiencySensor" + toString(myId)).c_str());
00280 }
00281 plot.SetXTitle("Threshold");
00282 plot.SetYTitle("Efficiency (%)");
00283 plot.SetBins(bins, low, high);
00284 for (std::vector<unsigned>::iterator it = myKnownThresholds.begin(); it
00285 != myKnownThresholds.end(); it++) {
00286 plot.Fill(*it, 100*getEfficiency(*it, withShapers, withSamplers));
00287 }
00288
00289 }
00290
00291 void MapsSensor::getEfficiencyByGroup(TH2F& plot, unsigned threshold) {
00292 plot.SetTitle(("Group efficiency for sensor " + toString(myId)).c_str());
00293 plot.SetName(("hGroupEfficiencySensor" + toString(myId)).c_str());
00294 plot.SetXTitle("Group + (Region x 6)");
00295 plot.SetYTitle("Row");
00296 plot.SetBins(28, 0, 28, 168, 0, 168);
00297
00298 bool doAllThresholds(false);
00299 if (threshold == 0)
00300 doAllThresholds = true;
00301 else {
00302
00303 MapsException me("Specifying a threshold isn't yet supported. Sorry.");
00304 throw me;
00305 }
00306
00307
00308
00309
00310 unsigned groupEff[29][168][2];
00311 memset(groupEff, 0, 2*168*29*sizeof(unsigned));
00312 unsigned region, group, pseudoGroup;
00313
00314 coord px;
00315 for (std::vector<MapsSensor::coord>::const_iterator it =
00316 myEfficientHits.begin(); it != myEfficientHits.end() ; ++it) {
00317 px = *it;
00318 try {
00319
00320
00321
00322 region = static_cast<unsigned>(px.first/42);
00323 assert(region < 4);
00324
00325 group = static_cast<unsigned>((px.first % 42) / 6);
00326 assert(group < 8);
00327
00328 pseudoGroup = region * 7 + group;
00329 assert(pseudoGroup < 29);
00330 ++groupEff[pseudoGroup][px.second][0];
00331 } catch (MapsException& me) {
00332 std::cout << __PRETTY_FUNCTION__ << __LINE__ << ": hmm, got a ME. Input hit: " << px << ", " << me.what() << "\n";
00333 }
00334 }
00335
00336 for (std::vector<MapsSensor::coord>::const_iterator it =
00337 myInefficientHits.begin(); it != myInefficientHits.end() ; ++it) {
00338 px = *it;
00339
00340 region = static_cast<unsigned>(px.first/42);
00341 assert(region < 4);
00342
00343 group = static_cast<unsigned>((px.first % 42) / 6);
00344 assert(group < 8);
00345
00346 pseudoGroup = region * 7 + group;
00347 assert(pseudoGroup < 29);
00348 ++groupEff[pseudoGroup][px.second][1];
00349 }
00350
00351 for (unsigned row(0); row < 168; ++row) {
00352 for (unsigned pseudoGrp(0); pseudoGrp < 29; ++pseudoGrp) {
00353 if ((groupEff[pseudoGrp][row][0] + groupEff[pseudoGrp][row][1])
00354 != 0) {
00355 plot.Fill(pseudoGrp, row,
00356 static_cast<double>(groupEff[pseudoGrp][row][0])
00357 / (groupEff[pseudoGrp][row][0]
00358 + groupEff[pseudoGrp][row][1]));
00359 }
00360 }
00361 }
00362
00363 }
00364 void MapsSensor::setResidual(MapsSensor::physXY resid) {
00365 myResiduals.push_back(resid);
00366 }
00367
00368 unsigned MapsSensor::getLowestThresh() const {
00369 unsigned lowest = 100000;
00370 for (std::vector<unsigned>::const_iterator it = myKnownThresholds.begin(); it
00371 != myKnownThresholds.end(); it++) {
00372 if (*it < lowest)
00373 lowest = *it;
00374 }
00375 return lowest;
00376 }
00377 unsigned MapsSensor::getHighestThresh() const {
00378 unsigned highest = 0;
00379 for (std::vector<unsigned>::const_iterator it = myKnownThresholds.begin(); it
00380 != myKnownThresholds.end(); it++) {
00381 if (*it > highest)
00382 highest = *it;
00383 }
00384 return highest;
00385 }
00386
00387 bool MapsSensor::isDeadArea(const physXY xyTest) const {
00388 physXY xy = xyTest;
00389 malign(xy);
00390 rotateGlobalToLocal(xy);
00391
00392
00393
00394 if (fabs(xy.second) < 0.025 || fabs(xy.second) > 4.225)
00395 return true;
00396
00397
00398 if (xy.first < -4.45)
00399 return true;
00400
00401 if (xy.first > 4.7)
00402 return true;
00403
00404 if (xy.first > -2.35 && xy.first < -2.1)
00405 return true;
00406
00407 if (xy.first > 0 && xy.first < 0.25)
00408 return true;
00409
00410 if (xy.first > 2.35 && xy.first < 2.6)
00411 return true;
00412
00413 return false;
00414
00415 }
00416
00417 void MapsSensor::convertHitToPhysical(const coord& c, physXY& xy) const {
00418
00419 int r = c.first / 42;
00420
00421
00422
00423 xy.first = (r - 2) * 2.35 + 0.25 + 0.025 + (c.first % 42) * 0.05;
00424
00425
00426 if (c.second > 83)
00427 xy.second = 0.05 + (c.second - 84) * 0.05;
00428 else
00429 xy.second = (c.second - 84) * 0.05;
00430
00431 physXY local(xy);
00432 rotateLocalToGlobal(xy);
00433 align(xy);
00434 assert(!isDeadArea(xy));
00435
00436
00437
00438 }
00439
00440 void MapsSensor::convertPhysicalToHit(const physXY& xyIn, coord& c) const
00441 throw(MapsException) {
00442
00443 if (isDeadArea(xyIn)) {
00444 std::string desc("Physical xy ");
00445 desc.append(toString(xyIn));
00446 desc.append(" falls in dead area.");
00447 MapsException me(desc.c_str());
00448 throw me;
00449 }
00450
00451 physXY xy = xyIn;
00452 malign(xy);
00453 rotateGlobalToLocal(xy);
00454
00455 unsigned r = static_cast<unsigned>(floor(xy.first/2.35) + 2);
00456
00457
00458 if (xy.second > 0.025)
00459 c.second = static_cast<unsigned>(84 + floor((xy.second - 0.025)/0.05));
00460 else
00461 c.second = static_cast<unsigned>(84 + floor((xy.second + 0.025)/0.05));
00462
00463
00464
00465 unsigned localX = static_cast<unsigned>(floor((xy.first - ((r - 2) * 2.35
00466 + 0.25)) / 0.05));
00467
00468
00469 c.first = r * 42 + localX;
00470
00471 }
00472
00473 unsigned MapsSensor::decodeRegion(const coord& input) const {
00474 return input.first / 42;
00475 }
00476
00477 unsigned MapsSensor::decodeRegion(const physXY& input) const throw(MapsException) {
00478 coord c;
00479 convertPhysicalToHit(input, c);
00480 return decodeRegion(c);
00481 }
00482
00483 void MapsSensor::rotateLocalToGlobal(physXY& local) const {
00484 MapsSensor::physXY localCpy = local;
00485 local.first = cos(myPhi) * localCpy.first + sin(myPhi) * localCpy.second;
00486 local.second = -1.0 * sin(myPhi) * localCpy.first + cos(myPhi)
00487 * localCpy.second;
00488 assert(fabs(pow(localCpy.first, 2) + pow(localCpy.second, 2) - pow(local.first, 2) - pow(local.second, 2)) < 0.01);
00489 }
00490
00491 void MapsSensor::rotateGlobalToLocal(physXY& glob) const {
00492 MapsSensor::physXY globCpy = glob;
00493 glob.first = cos(myPhi) * globCpy.first - sin(myPhi) * globCpy.second;
00494 glob.second = sin(myPhi) * globCpy.first + cos(myPhi) * globCpy.second;
00495 assert(fabs(pow(globCpy.first, 2) + pow(globCpy.second, 2) - pow(glob.first, 2) - pow(glob.second, 2)) < 0.01);
00496
00497 }
00498
00499 void MapsSensor::align(physXY& maligned) const {
00500 maligned.first = maligned.first + myAlignment.first;
00501 maligned.second = maligned.second + myAlignment.second;
00502 }
00503
00504 void MapsSensor::malign(physXY& aligned) const {
00505 aligned.first = aligned.first - myAlignment.first;
00506 aligned.second = aligned.second - myAlignment.second;
00507 }
00508
00509 void MapsSensor::printEfficiencies(std::ostream& s) {
00510 double sampYes(0), shapYes(0);
00511 double sampNo(0), shapNo(0);
00512 for (std::vector<unsigned>::const_iterator it = myKnownThresholds.begin(); it
00513 != myKnownThresholds.end(); ++it) {
00514 double efficiency = getEfficiency(*it);
00515 double shapEff = getEfficiency(*it, true, false);
00516 double sampEff = getEfficiency(*it, false, true);
00517 if (efficiency > -0.9) {
00518 s.precision(3);
00519
00520 shapYes += (myShaperHitsByThreshold[*it])->first;
00521 shapNo += (myShaperHitsByThreshold[*it])->second;
00522
00523 sampYes += (mySamplerHitsByThreshold[*it])->first;
00524 sampNo += (mySamplerHitsByThreshold[*it])->second;
00525
00526 s << "\t Thresh: " << *it << "\t: " << efficiency * 100
00527 << ",\t shap:\t" << shapEff * 100 << ",\t samp:\t"
00528 << sampEff * 100 << "\n";
00529 s << "\t\tShaper hits:\t " << (myShaperHitsByThreshold[*it])->first << " / " << (myShaperHitsByThreshold[*it])->first + (myShaperHitsByThreshold[*it])->second
00530 << "\tSampler hits:\t " << (mySamplerHitsByThreshold[*it])->first << " / " << (mySamplerHitsByThreshold[*it])->first + (mySamplerHitsByThreshold[*it])->second << "\n";
00531 }
00532
00533 }
00534 s << "\tOverall: \tShapers:\t" << shapYes << " / " << shapNo + shapYes
00535 << " = " << 100 * shapYes / (shapNo + shapYes);
00536 s << "\tSamplers:\t" << sampYes << " / " << sampNo + sampYes << " = "
00537 << 100 * sampYes / (sampNo + sampYes) << "\n";
00538 }
00539
00540 void MapsSensor::mutualSensorMask(
00541 const std::vector<MapsSensor*>& sensors, TH2F& mutual) {
00542 std::cout << __PRETTY_FUNCTION__ << std::endl;
00543 TRandom2 randy;
00544 double x, y;
00545 mutual.SetName("hExclusionArea");
00546 mutual.SetTitle("Mutual exclusion area");
00547 mutual.SetBins(1000, -5.0, 5.0, 1000, -5.0, 5.0);
00548 for (unsigned u(0); u < 100000; u++) {
00549 x = randy.Uniform(-5.0, 5.0);
00550 y = randy.Uniform(-5.0, 5.0);
00551 MapsSensor::physXY test(x, y);
00552
00553
00554
00555 unsigned deads = std::count_if(sensors.begin(), sensors.end(),
00556 std::bind2nd(IlEstMort(), test));
00557 if (deads > 0) {
00558 mutual.Fill(x, y);
00559 }
00560
00561 }
00562 }
00563
00564
00565 std::ostream& operator<<(std::ostream& s, const MapsSensor& ms) {
00566 return s << "Sensor id " << ms.myId << " [z=" << ms.myPosition
00567 << "\tphi_d=" << ms.myPhi/3.14159265358979323846 * 180.0
00568 << ",\tal=" << ms.myAlignment << "]";
00569 }
00570