Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-15 04:21:50

0001 #include "L1Trigger/L1TMuonOverlapPhase1/interface/Omtf/GoldenPatternResult.h"
0002 #include "L1Trigger/L1TMuonOverlapPhase1/interface/Omtf/OMTFConfiguration.h"
0003 
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 
0006 #include <iostream>
0007 #include <ostream>
0008 #include <iomanip>
0009 #include <cmath>
0010 
0011 ////////////////////////////////////////////
0012 ////////////////////////////////////////////
0013 
0014 ////////////////////////////////////////////
0015 ////////////////////////////////////////////
0016 GoldenPatternResult::GoldenPatternResult(const OMTFConfiguration* omtfConfig)
0017     : finalise([this]() { finalise0(); }), omtfConfig(omtfConfig) {
0018   if (omtfConfig)
0019     init(omtfConfig);
0020 }
0021 
0022 ////////////////////////////////////////////
0023 ////////////////////////////////////////////
0024 
0025 void GoldenPatternResult::set(int refLayer_, int phi, int eta, int refHitPhi) {
0026   if (isValid() && this->refLayer != refLayer_) {
0027     std::cout << __FUNCTION__ << " " << __LINE__ << " this->refLayer " << this->refLayer << " refLayer_ " << refLayer_
0028               << std::endl;
0029   }
0030   assert(!isValid() || this->refLayer == refLayer_);
0031 
0032   this->refLayer = refLayer_;
0033   this->phi = phi;
0034   this->eta = eta;
0035   this->refHitPhi = refHitPhi;
0036 }
0037 
0038 void GoldenPatternResult::setStubResult(float pdfVal, bool valid, int pdfBin, int layer, MuonStubPtr stub) {
0039   if (valid) {
0040     //pdfSum and firedLayerBits is calculated in finaliseX()
0041     firedLayerBits |= (1 << layer);
0042   }
0043   stubResults[layer] = StubResult(pdfVal, valid, pdfBin, layer, stub);
0044 
0045   //stub result is added even thought it is not valid since this might be needed for debugging or optimization
0046 }
0047 
0048 void GoldenPatternResult::setStubResult(int layer, StubResult& stubResult) {
0049   if (stubResult.getValid()) {
0050     //pdfSum and firedLayerBits is calculated in finaliseX()
0051     firedLayerBits |= (1 << layer);
0052   }
0053   stubResults[layer] = stubResult;
0054 
0055   //stub result is added even thought it is not valid since this might be needed for debugging or optimization
0056 }
0057 
0058 ////////////////////////////////////////////
0059 ////////////////////////////////////////////
0060 void GoldenPatternResult::init(const OMTFConfiguration* omtfConfig) {
0061   this->omtfConfig = omtfConfig;
0062 
0063   finalizeFunction = this->omtfConfig->getGoldenPatternResultFinalizeFunction();
0064 
0065   if (finalizeFunction == 1)
0066     finalise = [this]() { finalise1(); };
0067   else if (finalizeFunction == 2)
0068     finalise = [this]() { finalise2(); };
0069   else if (finalizeFunction == 3)
0070     finalise = [this]() { finalise3(); };
0071   else if (finalizeFunction == 5)
0072     finalise = [this]() { finalise5(); };
0073   else if (finalizeFunction == 6)
0074     finalise = [this]() { finalise6(); };
0075   else if (finalizeFunction == 7)
0076     finalise = [this]() { finalise7(); };
0077   else if (finalizeFunction == 8)
0078     finalise = [this]() { finalise8(); };
0079   else if (finalizeFunction == 9)
0080     finalise = [this]() { finalise9(); };
0081   else if (finalizeFunction == 10)
0082     finalise = [this]() { finalise10(); };
0083   else if (finalizeFunction == 11)
0084     finalise = [this]() { finalise11(); };
0085   else
0086     finalise = [this]() { finalise0(); };
0087 
0088   stubResults.assign(omtfConfig->nLayers(), StubResult());
0089   reset();
0090 }
0091 
0092 void GoldenPatternResult::reset() {
0093   for (auto& stubResult : stubResults) {
0094     stubResult.reset();
0095   }
0096   valid = false;
0097   refLayer = -1;
0098   phi = 0;
0099   eta = 0;
0100   pdfSum = 0;
0101   pdfSumUnconstr = 0;
0102   firedLayerCnt = 0;
0103   firedLayerBits = 0;
0104   refHitPhi = 0;
0105   gpProbability1 = 0;
0106   gpProbability2 = 0;
0107 }
0108 
0109 ////////////////////////////////////////////
0110 ////////////////////////////////////////////
0111 //default version
0112 void GoldenPatternResult::finalise0() {
0113   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0114     unsigned int connectedLayer = omtfConfig->getLogicToLogic().at(iLogicLayer);
0115     //here we require that in case of the DT layers, both phi and phiB is fired
0116     if (firedLayerBits & (1 << connectedLayer)) {
0117       if (firedLayerBits & (1 << iLogicLayer)) {
0118         //now in the GoldenPattern::process1Layer1RefLayer the pdf bin 0 is returned when the layer is not fired, so this is 'if' is to assured that this pdf val is not added here
0119         pdfSum += stubResults[iLogicLayer].getPdfVal();
0120 
0121         if (omtfConfig->fwVersion() <= 4) {
0122           if (!omtfConfig->getBendingLayers().count(iLogicLayer))
0123             //in DT case, the phi and phiB layers are threaded as one, so the firedLayerCnt is increased only for the phi layer
0124             firedLayerCnt++;
0125         } else
0126           firedLayerCnt++;
0127       }
0128     } else {
0129       firedLayerBits &= ~(1 << iLogicLayer);
0130     }
0131   }
0132 
0133   valid = true;
0134   //by default result becomes valid here, but can be overwritten later
0135 }
0136 
0137 ////////////////////////////////////////////
0138 ////////////////////////////////////////////
0139 //for the algo version with thresholds
0140 void GoldenPatternResult::finalise1() {
0141   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0142     //in this version we do not require that both phi and phiB is fired (non-zero), we thread them just independent
0143     //watch out that then the number of fired layers is bigger, and the cut on the minimal number of fired layers does not work in the same way as when the dt chamber is counted as one layer
0144     //TODO check if it affects performance
0145     pdfSum += stubResults[iLogicLayer].getPdfVal();
0146     firedLayerCnt += ((firedLayerBits & (1 << iLogicLayer)) != 0);
0147   }
0148 
0149   valid = true;
0150   //by default result becomes valid here, but can be overwritten later
0151 }
0152 
0153 ////////////////////////////////////////////
0154 ////////////////////////////////////////////
0155 //multiplication of PDF values instead of sum
0156 void GoldenPatternResult::finalise2() {
0157   pdfSum = 1.;
0158   firedLayerCnt = 0;
0159   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0160     unsigned int connectedLayer = omtfConfig->getLogicToLogic().at(iLogicLayer);
0161     //here we require that in case of the DT layers, both phi and phiB is fired
0162     if (firedLayerBits & (1 << connectedLayer)) {
0163       //now in the GoldenPattern::process1Layer1RefLayer the pdf bin 0 is returned when the layer is not fired, so this is 'if' is to assured that this pdf val is not added here
0164       if (firedLayerBits & (1 << iLogicLayer)) {
0165         pdfSum *= stubResults[iLogicLayer].getPdfVal();
0166         //in DT case, the phi and phiB layers are threaded as one, so the firedLayerCnt is increased only for the phi layer
0167         if (!omtfConfig->getBendingLayers().count(iLogicLayer))
0168           firedLayerCnt++;
0169       }
0170     } else {
0171       firedLayerBits &= ~(1 << iLogicLayer);
0172     }
0173   }
0174 
0175   if (firedLayerCnt < 3)
0176     pdfSum = 0;
0177 
0178   valid = true;
0179   //by default result becomes valid here, but can be overwritten later
0180 }
0181 
0182 ////////////////////////////////////////////
0183 ////////////////////////////////////////////
0184 //for patterns generation
0185 void GoldenPatternResult::finalise3() {
0186   firedLayerCnt = 0;
0187   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0188     //in this version we do not require that both phi and phiB is fired (non-zero), we thread them just independent
0189     //watch out that then the number of fired layers is bigger, and the cut on the minimal number of fired layers dies not work in the same way as when the dt chamber is counted as one layer
0190     //TODO check if it affects performance
0191     pdfSum += stubResults[iLogicLayer].getPdfVal();
0192 
0193     if (stubResults[iLogicLayer].getMuonStub())
0194       firedLayerCnt++;
0195   }
0196 
0197   valid = true;
0198   //by default result becomes valid here, but can be overwritten later
0199 }
0200 
0201 void GoldenPatternResult::finalise5() {
0202   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0203     unsigned int connectedLayer = omtfConfig->getLogicToLogic().at(iLogicLayer);
0204 
0205     if (omtfConfig->isBendingLayer(iLogicLayer)) {  //the DT phiB layer is counted only when the phi layer is fired
0206       if ((firedLayerBits & (1 << iLogicLayer)) && (firedLayerBits & (1 << connectedLayer))) {
0207         pdfSum += stubResults[iLogicLayer].getPdfVal();
0208         firedLayerCnt++;
0209       } else {
0210         firedLayerBits &= ~(1 << iLogicLayer);
0211         stubResults[iLogicLayer].setValid(false);
0212         //in principle the stun should be also removed from the stubResults[iLogicLayer], on the other hand ini this way can be used e.g. for debug
0213       }
0214     } else if (firedLayerBits & (1 << iLogicLayer)) {
0215       pdfSum += stubResults[iLogicLayer].getPdfVal();
0216       firedLayerCnt++;
0217     }
0218   }
0219 
0220   valid = true;
0221   //by default result becomes valid here, but can be overwritten later
0222 }
0223 
0224 void GoldenPatternResult::finalise6() {
0225   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0226     unsigned int connectedLayer = omtfConfig->getLogicToLogic().at(iLogicLayer);
0227 
0228     if (omtfConfig->isBendingLayer(iLogicLayer)) {  //the DT phiB layer is counted only when the phi layer is fired
0229       if ((firedLayerBits & (1 << iLogicLayer)) && (firedLayerBits & (1 << connectedLayer)) &&
0230           (stubResults[iLogicLayer].getMuonStub()->qualityHw >= 4)) {
0231         pdfSum += stubResults[iLogicLayer].getPdfVal();
0232         firedLayerCnt++;
0233       } else {
0234         firedLayerBits &= ~(1 << iLogicLayer);
0235         stubResults[iLogicLayer].setValid(false);
0236         //in principle the stun should be also removed from the stubResults[iLogicLayer], on the other hand ini this way can be used e.g. for debug
0237       }
0238     } else if (firedLayerBits & (1 << iLogicLayer)) {
0239       pdfSum += stubResults[iLogicLayer].getPdfVal();
0240       firedLayerCnt++;
0241     }
0242   }
0243 
0244   valid = true;
0245   //by default result becomes valid here, but can be overwritten later
0246 }
0247 
0248 void GoldenPatternResult::finalise7() {
0249   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0250     pdfSum += stubResults[iLogicLayer].getPdfVal();
0251     if (firedLayerBits & (1 << iLogicLayer)) {
0252       firedLayerCnt++;
0253     }
0254   }
0255 
0256   valid = true;
0257   //by default result becomes valid here, but can be overwritten later
0258 }
0259 
0260 void GoldenPatternResult::finalise8() {
0261   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0262     pdfSum += stubResults[iLogicLayer].getPdfVal();  //pdfSum is counted always
0263 
0264     unsigned int connectedLayer = omtfConfig->getLogicToLogic().at(iLogicLayer);
0265     if (omtfConfig->isBendingLayer(iLogicLayer)) {  //the DT phiB layer is counted only when the phi layer is fired
0266       if ((firedLayerBits & (1 << iLogicLayer)) && (firedLayerBits & (1 << connectedLayer))) {
0267         firedLayerCnt++;
0268       } else {
0269         firedLayerBits &= ~(1 << iLogicLayer);
0270         stubResults[iLogicLayer].setValid(false);
0271         //in principle the stub should be also removed from the stubResults[iLogicLayer], on the other hand in this way can be used e.g. for debug
0272       }
0273     } else if (firedLayerBits & (1 << iLogicLayer)) {
0274       firedLayerCnt++;
0275     }
0276   }
0277 
0278   valid = true;
0279   //by default result becomes valid here, but can be overwritten later
0280 }
0281 
0282 void GoldenPatternResult::finalise9() {
0283   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0284     unsigned int connectedLayer = omtfConfig->getLogicToLogic().at(iLogicLayer);
0285 
0286     if (omtfConfig->isBendingLayer(iLogicLayer)) {  //the DT phiB layer is counted only when the phi layer is fired
0287       if (firedLayerBits & (1 << iLogicLayer)) {
0288         if (firedLayerBits & (1 << connectedLayer)) {
0289           firedLayerCnt++;
0290           pdfSum += stubResults[iLogicLayer].getPdfVal();
0291         } else {
0292           firedLayerBits &= ~(1 << iLogicLayer);
0293           stubResults[iLogicLayer].setValid(false);
0294           //there was hit, but it did not fit to the pdf - this is not possible here, since the bending layer is fired here
0295           //therefore there is no sense to apply the penalty when the stubResults[iLogicLayer].getPdfVal() == 0
0296           //so in this case simply pdfSum += 0;
0297         }
0298       } else {
0299         if (stubResults[iLogicLayer].getPdfVal() == 0)
0300           //there is a hit, but does not fit to the pdf (therefore in firedLayerBits is 0, but getPdfVal() is not 0), so apply the penalty (-32)
0301           //N.B it is possible only with the patterns having "no hit value" and with noHitValueInPdf = True
0302           pdfSum -= 32;  // penaly
0303         else
0304           pdfSum += stubResults[iLogicLayer].getPdfVal();  //bending layer not fired at all
0305       }
0306     } else {
0307       if (iLogicLayer < 10 && stubResults[iLogicLayer].getPdfVal() == 0)
0308         pdfSum -= 32;  // penaly
0309       else
0310         pdfSum += stubResults[iLogicLayer].getPdfVal();
0311       if (firedLayerBits & (1 << iLogicLayer)) {  //pdfSum is counted always
0312         firedLayerCnt++;
0313       }
0314     }
0315   }
0316 
0317   valid = true;
0318   //by default result becomes valid here, but can be overwritten later
0319 }
0320 
0321 void GoldenPatternResult::finalise10() {
0322   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0323     unsigned int connectedLayer = omtfConfig->getLogicToLogic().at(iLogicLayer);
0324 
0325     if (omtfConfig->isBendingLayer(iLogicLayer)) {  //the DT phiB layer is counted only when the phi layer is fired
0326       if (firedLayerBits & (1 << iLogicLayer)) {
0327         if (firedLayerBits & (1 << connectedLayer)) {
0328           firedLayerCnt++;
0329           pdfSum += stubResults[iLogicLayer].getPdfVal();
0330         } else {
0331           firedLayerBits &= ~(1 << iLogicLayer);
0332           stubResults[iLogicLayer].setValid(false);
0333           //there is no sense to apply the penalty in this case,
0334           //because as the layer is fired, the stubResults[iLogicLayer].getPdfVal() cannot be 0
0335           //so in this case simply pdfSum += 0;
0336         }
0337       } else {
0338         //the penalty is not applied here when the phiB does not fit to the pdf
0339         //because when extrapolation from the ref layer using the phiB is applied
0340         //it "normal" for the displaced muons to not fit to the pdf
0341         pdfSum += stubResults[iLogicLayer].getPdfVal();
0342       }
0343     } else {
0344       if (iLogicLayer < 10 && stubResults[iLogicLayer].getPdfVal() == 0)
0345         pdfSum -= 32;  // penaly
0346       else
0347         pdfSum += stubResults[iLogicLayer].getPdfVal();
0348       if (firedLayerBits & (1 << iLogicLayer)) {  //pdfSum is counted always
0349         firedLayerCnt++;
0350       }
0351     }
0352   }
0353 
0354   if ((omtfConfig->usePhiBExtrapolationMB1() && refLayer == 0) ||
0355       (omtfConfig->usePhiBExtrapolationMB2() && refLayer == 2)) {
0356     auto refLayerLogicNumber = omtfConfig->getRefToLogicNumber()[refLayer];
0357     //Unconstrained pt is obtained by not including the pdfValue from the phiB of the refHit
0358     //TODO get logic layer from connectedLayer
0359     pdfSumUnconstr = pdfSum - stubResults[refLayerLogicNumber + 1].getPdfVal();
0360     //here there is an issue with the firedLayerBits and quality assignment:
0361     //in case if the displaced muon the phiB layer of the ref hit might not be fired (pdfVal might be 0)
0362     //which in principle has no sense, because by the displaced algorithm construction it is fired
0363     //an effect of that is that some fraction of displaced muons get the quality 8 assigned
0364     //the efficiency difference between quality 8 and 12 seems to be at a level of 1-2%
0365     //but in the uGT menu e.g. the L1_DoubleMu0_Upt6_IP_Min1_Upt4 uses quality >= 0, so should be OK
0366 
0367     //hard cut - the phiB of the refHit must fit to the pdfS
0368     //but this cut has sometimes side effect: there can be a muon which has has pdfSum = 0 for every pattern,
0369     //then in the OMTFSorter<GoldenPatternType>::sortRefHitResults the first pattern that has FiredLayerCnt >= 3 is chosen
0370     //and not the one with highest pdfSum as it should be
0371     //TODO what should be done is to set the pt of such a muons to 0, but after the sorter.
0372     //Or maybe not - if the pt is 0, then the muon is not valid. So the displaced muon will be lost.
0373     //So the way it is done now actually is good. Such a muon will have some low constrained pt probably.
0374     //what can be done is to assign to it the hwPt = 1 , but not 0
0375     //TODO modify this condition to use the firedLayerBits and not getPdfVal
0376     //as it would be much easier for the firmware
0377     if (stubResults[refLayerLogicNumber + 1].getPdfVal() == 0)
0378       pdfSum = 0;
0379   } else
0380     pdfSumUnconstr = 0;
0381 
0382   valid = true;
0383   //by default result becomes valid here, but can be overwritten later
0384 }
0385 
0386 //  the same as finalise10 but without:
0387 //if (stubResults[refLayerLogicNumber + 1].getPdfVal() == 0)
0388 //  pdfSum = 0;
0389 void GoldenPatternResult::finalise11() {
0390   for (unsigned int iLogicLayer = 0; iLogicLayer < stubResults.size(); ++iLogicLayer) {
0391     unsigned int connectedLayer = omtfConfig->getLogicToLogic().at(iLogicLayer);
0392 
0393     if (omtfConfig->isBendingLayer(iLogicLayer)) {  //the DT phiB layer is counted only when the phi layer is fired
0394       if (firedLayerBits & (1 << iLogicLayer)) {
0395         if (firedLayerBits & (1 << connectedLayer)) {
0396           firedLayerCnt++;
0397           pdfSum += stubResults[iLogicLayer].getPdfVal();
0398         } else {
0399           firedLayerBits &= ~(1 << iLogicLayer);
0400           stubResults[iLogicLayer].setValid(false);
0401           //there is no sense to apply the penalty in this case,
0402           //because as the layer is fired, the stubResults[iLogicLayer].getPdfVal() cannot be 0
0403           //so in this case simply pdfSum += 0;
0404         }
0405       } else {
0406         //bending layer fired, but not fits to the pdf, N.B works only with the patterns having "no hit value" and with noHitValueInPdf = True
0407         if (stubResults[iLogicLayer].getPdfVal() == 0) {
0408           //high penalty, we set the pdf value in the  stubResults[iLogicLayer], so that this penalty is removed from pdfSumUnconstr
0409           pdfSum -= 63;
0410           stubResults[iLogicLayer].setPdfVal(-63);
0411         } else
0412           pdfSum += stubResults[iLogicLayer].getPdfVal();  //bending layer not fired at all
0413       }
0414     } else {
0415       if (iLogicLayer < 10 && stubResults[iLogicLayer].getPdfVal() == 0)
0416         pdfSum -= 32;  // penaly
0417       else
0418         pdfSum += stubResults[iLogicLayer].getPdfVal();
0419       if (firedLayerBits & (1 << iLogicLayer)) {  //pdfSum is counted always
0420         firedLayerCnt++;
0421       }
0422     }
0423   }
0424 
0425   if ((omtfConfig->usePhiBExtrapolationMB1() && refLayer == 0) ||
0426       (omtfConfig->usePhiBExtrapolationMB2() && refLayer == 2)) {
0427     auto refLayerLogicNumber = omtfConfig->getRefToLogicNumber()[refLayer];
0428     //Unconstrained pt is obtained by not including the pdfValue from the phiB of the refHit
0429     //TODO get logic layer from connectedLayer
0430     pdfSumUnconstr = pdfSum - stubResults[refLayerLogicNumber + 1].getPdfVal();
0431 
0432   } else
0433     pdfSumUnconstr = 0;
0434 
0435   valid = true;
0436   //by default result becomes valid here, but can be overwritten later
0437 }
0438 
0439 ////////////////////////////////////////////
0440 ////////////////////////////////////////////
0441 std::ostream& operator<<(std::ostream& out, const GoldenPatternResult& gpResult) {
0442   if (gpResult.omtfConfig == nullptr) {
0443     out << "empty GoldenPatternResult" << std::endl;
0444     return out;
0445   }
0446   unsigned int refLayerLogicNum = gpResult.omtfConfig->getRefToLogicNumber()[gpResult.getRefLayer()];
0447 
0448   unsigned int sumOverFiredLayers = 0;
0449   for (unsigned int iLogicLayer = 0; iLogicLayer < gpResult.stubResults.size(); ++iLogicLayer) {
0450     out << " layer: " << std::setw(2) << iLogicLayer << " hit: ";
0451     if (gpResult.stubResults[iLogicLayer].getMuonStub()) {
0452       out << std::setw(4)
0453           << (gpResult.omtfConfig->isBendingLayer(iLogicLayer)
0454                   ? gpResult.stubResults[iLogicLayer].getMuonStub()->phiBHw
0455                   : gpResult.stubResults[iLogicLayer].getMuonStub()->phiHw);
0456 
0457       out << " pdfBin: " << std::setw(4) << gpResult.stubResults[iLogicLayer].getPdfBin() << " pdfVal: " << std::setw(3)
0458           << gpResult.stubResults[iLogicLayer].getPdfVal() << " fired " << gpResult.isLayerFired(iLogicLayer)
0459           << (iLogicLayer == refLayerLogicNum ? " <<< refLayer" : "");
0460 
0461       if (gpResult.isLayerFired(iLogicLayer))
0462         sumOverFiredLayers += gpResult.stubResults[iLogicLayer].getPdfVal();
0463     } else if (gpResult.stubResults[iLogicLayer].getPdfVal()) {
0464       out << "                  pdfVal: " << std::setw(3) << gpResult.stubResults[iLogicLayer].getPdfVal();
0465     }
0466     out << std::endl;
0467   }
0468 
0469   out << "  refLayer: ";
0470   out << gpResult.getRefLayer() << "\t";
0471 
0472   out << " Sum over layers: ";
0473   out << gpResult.getPdfSum() << "\t";
0474 
0475   out << " sumOverFiredLayers: ";
0476   out << sumOverFiredLayers << "\t";
0477 
0478   out << " Sum over layers unconstr: ";
0479   out << gpResult.getPdfSumUnconstr() << "\t";
0480 
0481   out << " Number of hits: ";
0482   out << gpResult.getFiredLayerCnt() << "\t";
0483 
0484   out << " GpProbability1: ";
0485   out << gpResult.getGpProbability1() << "\t";
0486 
0487   out << " GpProbability2: ";
0488   out << gpResult.getGpProbability2() << "\t";
0489 
0490   out << std::endl;
0491 
0492   return out;
0493 }
0494 ////////////////////////////////////////////
0495 ////////////////////////////////////////////