00001 #include "DataFormats/TrackReco/interface/HitPattern.h"
00002 #include "DataFormats/TrackingRecHit/interface/TrackingRecHit.h"
00003 #include "DataFormats/SiPixelDetId/interface/PXBDetId.h"
00004 #include "DataFormats/SiPixelDetId/interface/PXFDetId.h"
00005 #include "DataFormats/SiStripDetId/interface/TIBDetId.h"
00006 #include "DataFormats/SiStripDetId/interface/TIDDetId.h"
00007 #include "DataFormats/SiStripDetId/interface/TOBDetId.h"
00008 #include "DataFormats/SiStripDetId/interface/TECDetId.h"
00009 #include "DataFormats/MuonDetId/interface/DTLayerId.h"
00010 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
00011 #include "DataFormats/MuonDetId/interface/RPCDetId.h"
00012 using namespace reco;
00013
00014 void HitPattern::set(const TrackingRecHit & hit, unsigned int i) {
00015
00016 if (i >= 32 * PatternSize / HitSize) return;
00017
00018
00019 DetId id = hit.geographicalId();
00020 uint32_t detid = id.det();
00021 uint32_t hitType = (uint32_t) hit.getType();
00022
00023
00024 uint32_t pattern = 0;
00025
00026
00027 pattern += ((detid)&SubDetectorMask)<<SubDetectorOffset;
00028
00029
00030 uint32_t subdet = id.subdetId();
00031 pattern += ((subdet)&SubstrMask)<<SubstrOffset;
00032
00033
00034 uint32_t layer = 0;
00035 if (detid == DetId::Tracker) {
00036 if (subdet == PixelSubdetector::PixelBarrel)
00037 layer = PXBDetId(id).layer();
00038 else if (subdet == PixelSubdetector::PixelEndcap)
00039 layer = PXFDetId(id).disk();
00040 else if (subdet == StripSubdetector::TIB)
00041 layer = TIBDetId(id).layer();
00042 else if (subdet == StripSubdetector::TID)
00043 layer = TIDDetId(id).wheel();
00044 else if (subdet == StripSubdetector::TOB)
00045 layer = TOBDetId(id).layer();
00046 else if (subdet == StripSubdetector::TEC)
00047 layer = TECDetId(id).wheel();
00048 } else if (detid == DetId::Muon) {
00049 if (subdet == (uint32_t) MuonSubdetId::DT)
00050 layer = ((DTLayerId(id.rawId()).station()-1)<<2) + DTLayerId(id.rawId()).superLayer();
00051 else if (subdet == (uint32_t) MuonSubdetId::CSC)
00052 layer = ((CSCDetId(id.rawId()).station()-1)<<2) + (CSCDetId(id.rawId()).ring()-1);
00053 else if (subdet == (uint32_t) MuonSubdetId::RPC) {
00054 RPCDetId rpcid(id.rawId());
00055 layer = ((rpcid.station()-1)<<2) + abs(rpcid.region());
00056 if (rpcid.station() <= 2) layer += 2*(rpcid.layer()-1);
00057 }
00058 }
00059 pattern += (layer&LayerMask)<<LayerOffset;
00060
00061
00062 uint32_t side = 0;
00063 if (detid == DetId::Tracker) {
00064 side = isStereo(id);
00065 } else if (detid == DetId::Muon) {
00066 side = 0;
00067 }
00068 pattern += (side&SideMask)<<SideOffset;
00069
00070
00071 pattern += (hitType&HitTypeMask)<<HitTypeOffset;
00072
00073
00074 setHitPattern(i, pattern);
00075 }
00076
00077 void HitPattern::setHitPattern(int position, uint32_t pattern) {
00078 int offset = position * HitSize;
00079 for (int i=0; i<HitSize; i++) {
00080 int pos = offset + i;
00081 uint32_t bit = (pattern >> i) & 0x1;
00082 hitPattern_[pos / 32] += bit << ((offset + i) % 32);
00083 }
00084 }
00085
00086 uint32_t HitPattern::getHitPattern(int position) const {
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 uint16_t bitEndOffset = (position+1) * HitSize;
00106 uint8_t secondWord = (bitEndOffset >> 5);
00107 uint8_t secondWordBits = bitEndOffset & (32-1);
00108 if (secondWordBits >= HitSize) {
00109 uint8_t lowBitsToTrash = secondWordBits - HitSize;
00110 uint32_t myResult = (hitPattern_[secondWord] >> lowBitsToTrash) & ((1 << HitSize)-1);
00111 return myResult;
00112 } else {
00113 uint8_t firstWordBits = HitSize - secondWordBits;
00114 uint32_t firstWordBlock = hitPattern_[secondWord-1] >> (32-firstWordBits);
00115 uint32_t secondWordBlock = hitPattern_[secondWord] & ((1<<secondWordBits)-1);
00116 uint32_t myResult = firstWordBlock + (secondWordBlock << firstWordBits);
00117 return myResult;
00118 }
00119 }
00120
00121
00122
00123
00124
00125 bool HitPattern::hasValidHitInFirstPixelBarrel() const {
00126 for (int i=0; i<(PatternSize * 32) / HitSize; i++) {
00127 uint32_t pattern = getHitPattern(i);
00128 if (pattern == 0) break;
00129 if (pixelBarrelHitFilter(pattern)) {
00130 if (getLayer(pattern) == 1) {
00131 if (validHitFilter(pattern)) {
00132 return true;
00133 }
00134 }
00135 }
00136 }
00137 return false;
00138 }
00139
00140 bool HitPattern::hasValidHitInFirstPixelEndcap() const {
00141 for (int i=0; i<(PatternSize * 32) / HitSize; i++) {
00142 uint32_t pattern = getHitPattern(i);
00143 if (pattern == 0) break;
00144 if (pixelEndcapHitFilter(pattern)) {
00145 if (getLayer(pattern) == 1) {
00146 if (validHitFilter(pattern)) {
00147 return true;
00148 }
00149 }
00150 }
00151 }
00152 return false;
00153 }
00154
00155 int HitPattern::numberOfHits() const {
00156 int count = 0;
00157 for (int i=0; i<(PatternSize * 32) / HitSize; i++) {
00158 uint32_t pattern = getHitPattern(i);
00159 if (pattern == 0) break;
00160 ++count;
00161 }
00162 return count;
00163 }
00164
00165
00166 int HitPattern::numberOfValidStripLayersWithMonoAndStereo () const {
00167 static const int nHits = (PatternSize * 32) / HitSize;
00168 bool hasMono[SubstrMask + 1][LayerMask + 1];
00169
00170 memset(hasMono, 0, sizeof(hasMono));
00171 bool hasStereo[SubstrMask + 1][LayerMask + 1];
00172 memset(hasStereo, 0, sizeof(hasStereo));
00173
00174 for (int i = 0; i < nHits; i++) {
00175 uint32_t pattern = getHitPattern(i);
00176 if (pattern == 0) break;
00177 if (validHitFilter(pattern) && stripHitFilter(pattern)) {
00178 switch (getSide(pattern)) {
00179 case 0:
00180 hasMono[getSubStructure(pattern)][getLayer(pattern)]
00181 = true;
00182 break;
00183 case 1:
00184 hasStereo[getSubStructure(pattern)][getLayer(pattern)]
00185 = true;
00186 break;
00187 default:
00188 break;
00189 }
00190 }
00191
00192 }
00193
00194 int count = 0;
00195 for (int i = 0; i < SubstrMask + 1; ++i)
00196 for (int j = 0; j < LayerMask + 1; ++j)
00197 if (hasMono[i][j] && hasStereo[i][j])
00198 count++;
00199 return count;
00200 }
00201
00202 uint32_t HitPattern::getTrackerLayerCase(uint32_t substr, uint32_t layer) const {
00203 uint32_t tk_substr_layer =
00204 (1 << SubDetectorOffset) +
00205 ((substr & SubstrMask) << SubstrOffset) +
00206 ((layer & LayerMask) << LayerOffset);
00207
00208 uint32_t mask =
00209 (SubDetectorMask << SubDetectorOffset) +
00210 (SubstrMask << SubstrOffset) +
00211 (LayerMask << LayerOffset);
00212
00213
00214
00215
00216
00217
00218
00219
00220 uint32_t layerCase = 999999;
00221 for (int i=0; i<(PatternSize * 32) / HitSize; i++)
00222 {
00223 uint32_t pattern = getHitPattern(i);
00224 if (pattern == 0) break;
00225 if ((pattern & mask) == tk_substr_layer) {
00226 uint32_t hitType = (pattern >> HitTypeOffset) & HitTypeMask;
00227 if (hitType < layerCase) {
00228 layerCase = hitType;
00229 if (hitType == 3) layerCase = 2;
00230 }
00231 }
00232 }
00233 return layerCase;
00234 }
00235
00236 uint32_t HitPattern::getTrackerMonoStereo (uint32_t substr, uint32_t layer) const
00237 {
00238 uint32_t tk_substr_layer =
00239 (1 << SubDetectorOffset) +
00240 ((substr & SubstrMask) << SubstrOffset) +
00241 ((layer & LayerMask) << LayerOffset);
00242
00243 uint32_t mask =
00244 (SubDetectorMask << SubDetectorOffset) +
00245 (SubstrMask << SubstrOffset) +
00246 (LayerMask << LayerOffset);
00247
00248
00249
00250
00251
00252 uint32_t monoStereo = 0;
00253 for (int i=0; i<(PatternSize * 32) / HitSize; i++)
00254 {
00255 uint32_t pattern = getHitPattern(i);
00256 if (pattern == 0) break;
00257 if ((pattern & mask) == tk_substr_layer)
00258 {
00259 uint32_t hitType = (pattern >> HitTypeOffset) & HitTypeMask;
00260 if (hitType == 0) {
00261 switch (getSide(pattern)) {
00262 case 0:
00263 monoStereo |= MONO;
00264 break;
00265 case 1:
00266 monoStereo |= STEREO;
00267 break;
00268 default:
00269 break;
00270 }
00271 }
00272 }
00273 }
00274 return monoStereo;
00275 }
00276
00277
00278
00279 int HitPattern::pixelBarrelLayersWithMeasurement() const {
00280 int count = 0;
00281 uint32_t substr = PixelSubdetector::PixelBarrel;
00282 for (uint32_t layer=1; layer<=3; layer++) {
00283 if (getTrackerLayerCase(substr, layer) == 0) count++;
00284 }
00285 return count;
00286 }
00287
00288 int HitPattern::pixelEndcapLayersWithMeasurement() const {
00289 int count = 0;
00290 uint32_t substr = PixelSubdetector::PixelEndcap;
00291 for (uint32_t layer=1; layer<=2; layer++) {
00292 if (getTrackerLayerCase(substr, layer) == 0) count++;
00293 }
00294 return count;
00295 }
00296
00297 int HitPattern::stripTIBLayersWithMeasurement() const {
00298 int count = 0;
00299 uint32_t substr = StripSubdetector::TIB;
00300 for (uint32_t layer=1; layer<=4; layer++) {
00301 if (getTrackerLayerCase(substr, layer) == 0) count++;
00302 }
00303 return count;
00304 }
00305
00306 int HitPattern::stripTIDLayersWithMeasurement() const {
00307 int count = 0;
00308 uint32_t substr = StripSubdetector::TID;
00309 for (uint32_t layer=1; layer<=3; layer++) {
00310 if (getTrackerLayerCase(substr, layer) == 0) count++;
00311 }
00312 return count;
00313 }
00314
00315 int HitPattern::stripTOBLayersWithMeasurement() const {
00316 int count = 0;
00317 uint32_t substr = StripSubdetector::TOB;
00318 for (uint32_t layer=1; layer<=6; layer++) {
00319 if (getTrackerLayerCase(substr, layer) == 0) count++;
00320 }
00321 return count;
00322 }
00323
00324 int HitPattern::stripTECLayersWithMeasurement() const {
00325 int count = 0;
00326 uint32_t substr = StripSubdetector::TEC;
00327 for (uint32_t layer=1; layer<=9; layer++) {
00328 if (getTrackerLayerCase(substr, layer) == 0) count++;
00329 }
00330 return count;
00331 }
00332
00333
00334 int HitPattern::pixelBarrelLayersWithoutMeasurement() const {
00335 int count = 0;
00336 uint32_t substr = PixelSubdetector::PixelBarrel;
00337 for (uint32_t layer=1; layer<=3; layer++) {
00338 if (getTrackerLayerCase(substr, layer) == 1) count++;
00339 }
00340 return count;
00341 }
00342
00343 int HitPattern::pixelEndcapLayersWithoutMeasurement() const {
00344 int count = 0;
00345 uint32_t substr = PixelSubdetector::PixelEndcap;
00346 for (uint32_t layer=1; layer<=2; layer++) {
00347 if (getTrackerLayerCase(substr, layer) == 1) count++;
00348 }
00349 return count;
00350 }
00351
00352 int HitPattern::stripTIBLayersWithoutMeasurement() const {
00353 int count = 0;
00354 uint32_t substr = StripSubdetector::TIB;
00355 for (uint32_t layer=1; layer<=4; layer++) {
00356 if (getTrackerLayerCase(substr, layer) == 1) count++;
00357 }
00358 return count;
00359 }
00360
00361 int HitPattern::stripTIDLayersWithoutMeasurement() const {
00362 int count = 0;
00363 uint32_t substr = StripSubdetector::TID;
00364 for (uint32_t layer=1; layer<=3; layer++) {
00365 if (getTrackerLayerCase(substr, layer) == 1) count++;
00366 }
00367 return count;
00368 }
00369
00370 int HitPattern::stripTOBLayersWithoutMeasurement() const {
00371 int count = 0;
00372 uint32_t substr = StripSubdetector::TOB;
00373 for (uint32_t layer=1; layer<=6; layer++) {
00374 if (getTrackerLayerCase(substr, layer) == 1) count++;
00375 }
00376 return count;
00377 }
00378
00379 int HitPattern::stripTECLayersWithoutMeasurement() const {
00380 int count = 0;
00381 uint32_t substr = StripSubdetector::TEC;
00382 for (uint32_t layer=1; layer<=9; layer++) {
00383 if (getTrackerLayerCase(substr, layer) == 1) count++;
00384 }
00385 return count;
00386 }
00387
00388
00389 int HitPattern::pixelBarrelLayersTotallyOffOrBad() const {
00390 int count = 0;
00391 uint32_t substr = PixelSubdetector::PixelBarrel;
00392 for (uint32_t layer=1; layer<=3; layer++) {
00393 if (getTrackerLayerCase(substr, layer) == 2) count++;
00394 }
00395 return count;
00396 }
00397
00398 int HitPattern::pixelEndcapLayersTotallyOffOrBad() const {
00399 int count = 0;
00400 uint32_t substr = PixelSubdetector::PixelEndcap;
00401 for (uint32_t layer=1; layer<=2; layer++) {
00402 if (getTrackerLayerCase(substr, layer) == 2) count++;
00403 }
00404 return count;
00405 }
00406
00407 int HitPattern::stripTIBLayersTotallyOffOrBad() const {
00408 int count = 0;
00409 uint32_t substr = StripSubdetector::TIB;
00410 for (uint32_t layer=1; layer<=4; layer++) {
00411 if (getTrackerLayerCase(substr, layer) == 2) count++;
00412 }
00413 return count;
00414 }
00415
00416 int HitPattern::stripTIDLayersTotallyOffOrBad() const {
00417 int count = 0;
00418 uint32_t substr = StripSubdetector::TID;
00419 for (uint32_t layer=1; layer<=3; layer++) {
00420 if (getTrackerLayerCase(substr, layer) == 2) count++;
00421 }
00422 return count;
00423 }
00424
00425 int HitPattern::stripTOBLayersTotallyOffOrBad() const {
00426 int count = 0;
00427 uint32_t substr = StripSubdetector::TOB;
00428 for (uint32_t layer=1; layer<=6; layer++) {
00429 if (getTrackerLayerCase(substr, layer) == 2) count++;
00430 }
00431 return count;
00432 }
00433
00434 int HitPattern::stripTECLayersTotallyOffOrBad() const {
00435 int count = 0;
00436 uint32_t substr = StripSubdetector::TEC;
00437 for (uint32_t layer=1; layer<=9; layer++) {
00438 if (getTrackerLayerCase(substr, layer) == 2) count++;
00439 }
00440 return count;
00441 }
00442
00443
00444 int HitPattern::pixelBarrelLayersNull() const {
00445 int count = 0;
00446 uint32_t substr = PixelSubdetector::PixelBarrel;
00447 for (uint32_t layer=1; layer<=3; layer++) {
00448 if (getTrackerLayerCase(substr, layer) == 999999) count++;
00449 }
00450 return count;
00451 }
00452
00453 int HitPattern::pixelEndcapLayersNull() const {
00454 int count = 0;
00455 uint32_t substr = PixelSubdetector::PixelEndcap;
00456 for (uint32_t layer=1; layer<=2; layer++) {
00457 if (getTrackerLayerCase(substr, layer) == 999999) count++;
00458 }
00459 return count;
00460 }
00461
00462 int HitPattern::stripTIBLayersNull() const {
00463 int count = 0;
00464 uint32_t substr = StripSubdetector::TIB;
00465 for (uint32_t layer=1; layer<=4; layer++) {
00466 if (getTrackerLayerCase(substr, layer) == 999999) count++;
00467 }
00468 return count;
00469 }
00470
00471 int HitPattern::stripTIDLayersNull() const {
00472 int count = 0;
00473 uint32_t substr = StripSubdetector::TID;
00474 for (uint32_t layer=1; layer<=3; layer++) {
00475 if (getTrackerLayerCase(substr, layer) == 999999) count++;
00476 }
00477 return count;
00478 }
00479
00480 int HitPattern::stripTOBLayersNull() const {
00481 int count = 0;
00482 uint32_t substr = StripSubdetector::TOB;
00483 for (uint32_t layer=1; layer<=6; layer++) {
00484 if (getTrackerLayerCase(substr, layer) == 999999) count++;
00485 }
00486 return count;
00487 }
00488
00489 int HitPattern::stripTECLayersNull() const {
00490 int count = 0;
00491 uint32_t substr = StripSubdetector::TEC;
00492 for (uint32_t layer=1; layer<=9; layer++) {
00493 if (getTrackerLayerCase(substr, layer) == 999999) count++;
00494 }
00495 return count;
00496 }
00497
00498 void HitPattern::printHitPattern (int position, std::ostream &stream) const
00499 {
00500 uint32_t pattern = getHitPattern(position);
00501 stream << "\t";
00502 if (muonHitFilter(pattern))
00503 stream << "muon";
00504 if (trackerHitFilter(pattern))
00505 stream << "tracker";
00506 stream << "\tsubstructure " << getSubStructure(pattern);
00507 if (muonHitFilter(pattern)) {
00508 stream << "\tstation " << getMuonStation(pattern);
00509 if (muonDTHitFilter(pattern)) {
00510 stream << "\tdt superlayer " << getDTSuperLayer(pattern);
00511 } else if (muonCSCHitFilter(pattern)) {
00512 stream << "\tcsc ring " << getCSCRing(pattern);
00513 } else if (muonRPCHitFilter(pattern)) {
00514 stream << "\trpc " << (getRPCregion(pattern) ? "endcaps" : "barrel") << ", layer " << getRPCLayer(pattern);
00515 } else {
00516 stream << "(UNKNOWN Muon SubStructure!) \tsubsubstructure " << getSubStructure(pattern);
00517 }
00518 } else {
00519 stream << "\tlayer " << getLayer(pattern);
00520 }
00521 stream << "\thit type " << getHitType(pattern);
00522 stream << std::endl;
00523 }
00524
00525 void HitPattern::print (std::ostream &stream) const
00526 {
00527 stream << "HitPattern" << std::endl;
00528 for (int i = 0; i < numberOfHits(); i++)
00529 printHitPattern(i, stream);
00530 std::ios_base::fmtflags flags = stream.flags();
00531 stream.setf ( std::ios_base::hex, std::ios_base::basefield );
00532 stream.setf ( std::ios_base::showbase );
00533 for (int i = 0; i < numberOfHits(); i++) {
00534 uint32_t pattern = getHitPattern(i);
00535 stream << pattern << std::endl;
00536 }
00537 stream.flags(flags);
00538 }
00539
00540 uint32_t HitPattern::isStereo (DetId i)
00541 {
00542 switch (i.det()) {
00543 case DetId::Tracker:
00544 switch (i.subdetId()) {
00545 case PixelSubdetector::PixelBarrel:
00546 case PixelSubdetector::PixelEndcap:
00547 return 0;
00548 case StripSubdetector::TIB:
00549 {
00550 TIBDetId id = i;
00551 return id.isStereo();
00552 }
00553 case StripSubdetector::TID:
00554 {
00555 TIDDetId id = i;
00556 return id.isStereo();
00557 }
00558 case StripSubdetector::TOB:
00559 {
00560 TOBDetId id = i;
00561 return id.isStereo();
00562 }
00563 case StripSubdetector::TEC:
00564 {
00565 TECDetId id = i;
00566 return id.isStereo();
00567 }
00568 default:
00569 return 0;
00570 }
00571 break;
00572 default:
00573 return 0;
00574 }
00575 }
00576
00577 int HitPattern::muonStations(int subdet, int hitType) const {
00578 int stations[4] = { 0,0,0,0 };
00579 for (int i=0; i<(PatternSize * 32) / HitSize; i++) {
00580 uint32_t pattern = getHitPattern(i);
00581 if (pattern == 0) break;
00582 if (muonHitFilter(pattern) &&
00583 (subdet == 0 || int(getSubStructure(pattern)) == subdet) &&
00584 (hitType == -1 || int(getHitType(pattern)) == hitType)) {
00585 stations[getMuonStation(pattern)-1] = 1;
00586 }
00587 }
00588 return stations[0]+stations[1]+stations[2]+stations[3];
00589 }
00590
00591
00592 int HitPattern::innermostMuonStationWithHits(int hitType) const {
00593 int ret = 0;
00594 for (int i=0; i<(PatternSize * 32) / HitSize; i++) {
00595 uint32_t pattern = getHitPattern(i);
00596 if (pattern == 0) break;
00597 if (muonHitFilter(pattern) &&
00598 (hitType == -1 || int(getHitType(pattern)) == hitType)) {
00599 int stat = getMuonStation(pattern);
00600 if (ret == 0 || stat < ret) ret = stat;
00601 }
00602 }
00603 return ret;
00604 }
00605
00606 int HitPattern::outermostMuonStationWithHits(int hitType) const {
00607 int ret = 0;
00608 for (int i=0; i<(PatternSize * 32) / HitSize; i++) {
00609 uint32_t pattern = getHitPattern(i);
00610 if (pattern == 0) break;
00611 if (muonHitFilter(pattern) &&
00612 (hitType == -1 || int(getHitType(pattern)) == hitType)) {
00613 int stat = getMuonStation(pattern);
00614 if (ret == 0 || stat > ret) ret = stat;
00615 }
00616 }
00617 return ret;
00618 }
00619
00620
00621 int HitPattern::numberOfDTStationsWithRPhiView() const {
00622 int stations[4] = { 0,0,0,0 };
00623 for (int i=0; i<(PatternSize * 32) / HitSize; i++) {
00624 uint32_t pattern = getHitPattern(i);
00625 if (pattern == 0) break;
00626 if (muonDTHitFilter(pattern) && validHitFilter(pattern) && getDTSuperLayer(pattern) != 2) {
00627 stations[getMuonStation(pattern)-1] = 1;
00628 }
00629 }
00630 return stations[0]+stations[1]+stations[2]+stations[3];
00631 }
00632
00633 int HitPattern::numberOfDTStationsWithRZView() const {
00634 int stations[4] = { 0,0,0,0 };
00635 for (int i=0; i<(PatternSize * 32) / HitSize; i++) {
00636 uint32_t pattern = getHitPattern(i);
00637 if (pattern == 0) break;
00638 if (muonDTHitFilter(pattern) && validHitFilter(pattern) && getDTSuperLayer(pattern) == 2) {
00639 stations[getMuonStation(pattern)-1] = 1;
00640 }
00641 }
00642 return stations[0]+stations[1]+stations[2]+stations[3];
00643 }
00644
00645 int HitPattern::numberOfDTStationsWithBothViews() const {
00646 int stations[4][2] = { {0,0}, {0,0}, {0,0}, {0,0} };
00647 for (int i=0; i<(PatternSize * 32) / HitSize; i++) {
00648 uint32_t pattern = getHitPattern(i);
00649 if (pattern == 0) break;
00650 if (muonDTHitFilter(pattern) && validHitFilter(pattern)) {
00651 stations[getMuonStation(pattern)-1][getDTSuperLayer(pattern) == 2] = 1;
00652 }
00653 }
00654 return stations[0][0]*stations[0][1] + stations[1][0]*stations[1][1] + stations[2][0]*stations[2][1] + stations[3][0]*stations[3][1];
00655 }
00656
00657
00658