00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <math.h>
00015 #include <iostream>
00016 #include "MdcGeom/Constants.h"
00017 #include "MdcGeom/BesAngle.h"
00018 #include "CLHEP/Alist/AList.h"
00019 #include "MdcData/MdcRecoHitOnTrack.h"
00020 #include "MdcRawEvent/MdcDigi.h"
00021 #include "MdcData/MdcHitMap.h"
00022 #include "MdcData/MdcHit.h"
00023 #include "MdcGeom/MdcDetector.h"
00024 #include "MdcTrkRecon/MdcSeg.h"
00025 #include "MdcTrkRecon/MdcSegList.h"
00026 #include "MdcTrkRecon/MdcTrackList.h"
00027 #include "MdcTrkRecon/mdcWrapWire.h"
00028 #include "MdcTrkRecon/MdcTrackParams.h"
00029 #include "MdcTrkRecon/MdcSegGrouperSt.h"
00030 #include "MdcTrkRecon/MdcSegGrouperAx.h"
00031 #include "MdcTrkRecon/MdcSegInfo.h"
00032 #include "MdcTrkRecon/MdcSegInfoAxialO.h"
00033 #include "MdcTrkRecon/MdcTrack.h"
00034 #include "MdcTrkRecon/GmsList.h"
00035 #include "TrkBase/TrkRecoTrk.h"
00036 #include "TrkBase/TrkHitOnTrk.h"
00037 #include "TrkBase/TrkHotList.h"
00038 #include "TrkBase/TrkFit.h"
00039 #include "TrkBase/TrkFitStatus.h"
00040 #include "TrkBase/TrkExchangePar.h"
00041 #include "TrkBase/TrkErrCode.h"
00042 #include "TrkFitter/TrkHelixMaker.h"
00043 #include "TrkFitter/TrkCircleMaker.h"
00044 #include "MdcGeom/Constants.h"
00045 #include "BField/BField.h"
00046
00047
00048 #include "GaudiKernel/NTuple.h"
00049 #include "AIDA/IHistogram1D.h"
00050 #include "Rtypes.h"
00051 extern int haveDigiTk[43][288];
00052 extern double haveDigiDrift[43][288];
00053 extern AIDA::IHistogram1D* g_cirTkChi2;
00054 extern AIDA::IHistogram1D* g_3dTkChi2;
00055 extern AIDA::IHistogram1D* g_fitNAct;
00056 extern AIDA::IHistogram1D* g_pickHitWire;
00057
00058 extern NTuple::Tuple* m_tuplePick;
00059 extern NTuple::Item<long> m_pickIs2D;
00060 extern NTuple::Item<long> m_pickLayer;
00061 extern NTuple::Item<long> m_pickNCell;
00062 extern NTuple::Item<long> m_pickNCellWithDigi;
00063 extern NTuple::Array<long> m_pickWire;
00064 extern NTuple::Array<double> m_pickPredDrift;
00065 extern NTuple::Array<double> m_pickDrift;
00066 extern NTuple::Array<double> m_pickDriftTruth;
00067 extern NTuple::Array<int> m_pickPhizOk;
00068 extern NTuple::Array<double> m_pickZ;
00069 extern NTuple::Array<double> m_pickResid;
00070 extern NTuple::Array<double> m_pickSigma;
00071 extern NTuple::Array<double> m_pickPhiLowCut;
00072 extern NTuple::Array<double> m_pickPhiHighCut;
00073 extern NTuple::Array<double> m_pickDriftCut;
00074 extern NTuple::Array<long> m_pickMcTk;
00075 extern NTuple::Array<double> m_pickPt;
00076 extern NTuple::Array<double> m_pickCurv;
00077
00078
00079
00080 #ifdef MDCPATREC_TIMETEST
00081
00082 #include <Profile/Profiler.h>
00083 #include <sys/time.h>
00084 #include <pthread.h>
00085 #endif
00086
00087 using std::cout;
00088 using std::endl;
00089
00090
00091 MdcTrackList::MdcTrackList(const MdcTrackParams &tkPar ) :
00092 MdcTrackListBase(tkPar) {
00093
00094 return;
00095 }
00096
00097
00098 MdcTrackList::~MdcTrackList() {}
00099
00100
00101
00102 int
00103 MdcTrackList::createFromSegs(MdcSegList *segs, const MdcHitMap* map,
00104 const MdcDetector* gm,
00105 TrkContext& context, double bunchTime) {
00106
00107
00108 int nTracks = 0;
00109
00110 m_debug = tkParam.lPrint;
00111
00112
00113 MdcSegGrouperSt stereoSegs(gm, tkParam.lPrint);
00114
00115
00116
00117
00118 #ifdef MDCPATREC_TIMETEST
00119 TAU_PROFILE_TIMER(timer8,"fill ax seg", "int ()", TAU_DEFAULT);
00120 TAU_PROFILE_START(timer8);
00121 #endif
00122 MdcSegGrouperAx origSegs(gm, tkParam.lPrint);
00123 origSegs.fillWithSegs(segs);
00124
00125
00126 #ifdef MDCPATREC_TIMETEST
00127 TAU_PROFILE_STOP(timer8);
00128 #endif
00129 MdcSeg *seed;
00130 bool goodOnly = true;
00131 bool useBad = (segs->count() < 400);
00132
00133 segs->resetSeed(gm);
00134 MdcTrack *trialTrack = 0;
00135
00136 while (1) {
00137 seed = segs->getSeed(0,goodOnly);
00138 if (seed == 0 && goodOnly && useBad) {
00139 segs->resetSeed(gm);
00140 goodOnly = false;
00141 continue;
00142 }
00143 else if (seed == 0 && (!goodOnly || !useBad)) {
00144 break;
00145 }
00146
00147 if (3 == m_debug) dumpSeed(seed, goodOnly);
00148
00149
00150 if ( fabs( ((MdcSegInfoAxialO *) seed->info())->curv()) > 0.0417) continue;
00151 delete trialTrack;
00152 trialTrack = 0;
00153
00154
00155 #ifdef MDCPATREC_TIMETEST
00156 TAU_PROFILE_TIMER(timer3,"combine ax seg", "int ()", TAU_DEFAULT);
00157 TAU_PROFILE_START(timer3);
00158 #endif
00159 int success = origSegs.combineSegs(trialTrack, seed, context, bunchTime,
00160 tkParam.maxSegChisqO);
00161 #ifdef MDCPATREC_TIMETEST
00162 TAU_PROFILE_STOP(timer3);
00163 #endif
00164
00165
00166 if (3 <= m_debug){
00167 cout<<" ***** Ax.combineSegs success? " << success<<"\n";
00168 dumpAxCombine(trialTrack);
00169 }
00170 if (!success) continue;
00171
00172
00173
00174 #ifdef MDCPATREC_TIMETEST
00175 TAU_PROFILE_TIMER(timer4,"circle fitting", "int ()", TAU_DEFAULT);
00176 TAU_PROFILE_START(timer4);
00177 #endif
00178 success = finishCircle(*trialTrack, map, gm);
00179 #ifdef MDCPATREC_TIMETEST
00180 TAU_PROFILE_STOP(timer4);
00181 #endif
00182
00183 if (3 <= m_debug){
00184 cout<<"finishCircle success? " << success<<"\n";
00185 dumpCircle(trialTrack);
00186 }
00187
00188 if (!success) continue;
00189
00190 const TrkFit* tkFit = trialTrack->track().fitResult();
00191 assert (tkFit != 0);
00192 TrkExchangePar par = tkFit->helix(0.0);
00193
00194
00195
00196
00197
00198
00199 if ( (m_d0Cut > Constants::epsilon) && (fabs(par.d0()) > m_d0Cut) ){
00200 if (tkParam.lPrint>1)cout<<__FILE__<<" Killing track by d0:" <<par.d0()<<">"<<m_d0Cut << endl;
00201 continue;
00202 }
00203
00204
00205 if ( (fabs(m_ptCut)>0.) && (fabs(tkFit->pt(0.)) < m_ptCut) ){
00206 if (tkParam.lPrint>1)cout<<__FILE__<<" Killing track by pt:" <<tkFit->pt(0.)<<"<"<<m_ptCut << endl;
00207 continue;
00208 }
00209
00210
00211 if (3 <= m_debug) std::cout << " *** End r-phi track-finding "<<std::endl;
00212
00213
00214 #ifdef MDCPATREC_TIMETEST
00215 TAU_PROFILE_TIMER(timer5,"fill st seg", "int ()", TAU_DEFAULT);
00216 TAU_PROFILE_START(timer5);
00217 #endif
00218 stereoSegs.fillWithSegs(segs, trialTrack);
00219 #ifdef MDCPATREC_TIMETEST
00220 TAU_PROFILE_STOP(timer5);
00221 #endif
00222 if (3 <= m_debug){
00223
00224 std::cout<<std::endl<<"----------------------------------------"<< std::endl;
00225 std::cout<<" Segment list after St.fillWithSegs "<< std::endl;
00226 stereoSegs.dumpSegList();
00227 }
00228
00229 #ifdef MDCPATREC_TIMETEST
00230 TAU_PROFILE_TIMER(timer6,"combine st seg", "int ()", TAU_DEFAULT);
00231 TAU_PROFILE_START(timer6);
00232 #endif
00233 success = stereoSegs.combineSegs(trialTrack, 0, context, bunchTime,
00234 tkParam.maxSegChisqO, tkParam.combineByFitHits);
00235 #ifdef MDCPATREC_TIMETEST
00236 TAU_PROFILE_STOP(timer6);
00237 #endif
00238
00239 if (3 <= m_debug){
00240 cout<<" ***** St.combineSegs success? " << success<<"\n";
00241 dumpStCombine(trialTrack);
00242 }
00243
00244
00245
00246 if (success) {
00247 #ifdef MDCPATREC_TIMETEST
00248 TAU_PROFILE_TIMER(timer7,"helix fitting", "int ()", TAU_DEFAULT);
00249 TAU_PROFILE_START(timer7);
00250 #endif
00251 success = finishHelix(*trialTrack, map, gm);
00252 #ifdef MDCPATREC_TIMETEST
00253 TAU_PROFILE_STOP(timer7);
00254 #endif
00255 }
00256
00257 if (3 == m_debug){
00258 dumpHelix(trialTrack);
00259 }
00260 if (!success) continue;
00261
00262
00263
00264 double d0par = trialTrack->track().fitResult()->helix(0.).d0();
00265 if ( (m_d0Cut > Constants::epsilon) && (fabs(d0par) > m_d0Cut) ){
00266 if (tkParam.lPrint>1) {cout<<__FILE__
00267 <<" Killing track by d0 after 3d fit:" <<d0par<<">"<<m_d0Cut << endl;}
00268 continue;
00269 }
00270
00271 double z0par = trialTrack->track().fitResult()->helix(0.).z0();
00272 if ( (m_z0Cut > Constants::epsilon) && (fabs(z0par) > m_z0Cut) ){
00273 if (tkParam.lPrint>1) {cout<<__FILE__
00274 <<" Killing track by z0:" <<z0par<<">"<<m_z0Cut << endl;}
00275 continue;
00276 }
00277
00278
00279 nTracks++;
00280 append(trialTrack);
00281
00282 trialTrack = 0;
00283
00284 if (3 == m_debug) std::cout << " ***** End one track-finding *****"<<std::endl;
00285 }
00286
00287 delete trialTrack;
00288 return nTracks;
00289
00290 }
00291
00292
00293
00294 int
00295 MdcTrackList::pickHits(MdcTrack *trk, const MdcHitMap* map,
00296 const MdcDetector* gm, bool pickAm) {
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 bool is2d = trk->track().status()->is2d();
00307 if(6==tkParam.lPrint){
00308 cout << "Before pickHits";
00309 if (is2d) cout<<" 2d:";
00310 else cout<<" 3d:";
00311 cout<< endl;
00312 }
00313
00314 int nFound = 0;
00315 int nCand = 0;
00316 double rMin, rMax;
00317 double rEnter, rExit;
00318 BesAngle phiEnter, phiExit;
00319 int wireLow, wireHigh;
00320 double phiLow, phiHigh;
00321 int nCell;
00322 MdcHit *thisHit;
00323 HepAList<MdcHitOnTrack> localHistory;
00324
00325 double cellWidth;
00326 double goodDriftCut;
00327 double aresid = 0.;
00328 int firstInputHit = -1;
00329 int lCurl = 0;
00330
00331
00332 const MdcLayer *firstInputLayer = trk->firstLayer();
00333 const MdcLayer *lastInputLayer = trk->lastLayer();
00334
00335 double bunchTime = trk->track().trackT0();
00336 const TrkFit* tkFit = trk->track().fitResult();
00337 assert (tkFit != 0);
00338 const TrkFitStatus* tkStatus = trk->track().status();
00339 assert (tkStatus != 0);
00340 TrkHitList* hitList = trk->track().hits();
00341 assert (hitList != 0);
00342 TrkExchangePar par = tkFit->helix(0.0);
00343 double d0 = par.d0();
00344 double curv = 0.5 * par.omega();
00345 double sinPhi0 = sin(par.phi0());
00346 double cosPhi0 = cos(par.phi0());
00347
00348
00349 rMin = gm->firstLayer()->rIn();
00350 double absd0 = fabs(d0);
00351 if (absd0 > rMin) rMin = absd0 + Constants::epsilon;
00352
00353 bool willCurl = false;
00354 double rCurl = fabs(d0 + 1./curv);
00355 rMax = gm->lastLayer()->rOut();
00356
00357 if (rCurl < rMax) {
00358 willCurl = true;
00359 rMax = rCurl - Constants::epsilon;
00360 }
00361
00362 bool reachedLastInput = false;
00363 bool hasCurled = false;
00364
00365
00366 bool isHotOnLayer[43];
00367 if(tkParam.pickSkipExistLayer){
00368 for(int ii=0; ii<43; ii++) isHotOnLayer[ii]=false;
00369 for (TrkHitList::hot_iterator ihit(hitList->begin()); ihit != hitList->end(); ++ihit){
00370 isHotOnLayer[ihit->layerNumber()]=true;
00371 }
00372 }
00373
00374
00375
00376 for (const MdcLayer *layer = gm->firstLayer(); layer != 0;
00377 layer = ((!lCurl) ? ( (hasCurled) ? gm->prevLayer(layer) :
00378 gm->nextLayer(layer)) : layer) ) {
00379
00380
00381 if (lCurl) {
00382 lCurl = 0;
00383 hasCurled = true;
00384 }
00385 if (tkStatus->is2d() && layer->view() != 0) continue;
00386
00387 if(tkParam.pickSkipExistLayer && isHotOnLayer[layer->layNum()]) continue;
00388
00389
00390
00391 bool lContinue = true;
00392 if(tkParam.pickUitlLastLayer) {
00393 if (layer == lastInputLayer) reachedLastInput = true;
00394 }
00395
00396
00397 if (hasCurled) {
00398 rEnter = layer->rOut();
00399 if (rEnter < rMin) {
00400
00401
00402 break;
00403 }
00404 rExit = layer->rIn();
00405 if (rExit < rMin) rExit = rMin;
00406 if (rEnter > rMax) rEnter = rMax;
00407
00408
00409
00410 } else {
00411 rEnter = layer->rIn();
00412 rExit = layer->rOut();
00413
00414
00415 if (rExit < rMin) continue;
00416
00417 if (willCurl) {
00418 if (rEnter > rMax) {
00419
00420
00421 hasCurled = 1;
00422 continue;
00423 }
00424 if (rExit > rMax) {
00425 lCurl = 1;
00426 rExit = rMax;
00427 }
00428 } else {
00429
00430 if (rEnter > rMax) {
00431
00432 break;
00433 }
00434 if (rExit > rMax) rExit = rMax;
00435 }
00436 }
00437
00438 nCell = layer->nWires();
00439 cellWidth = Constants::twoPi * layer->rMid() / nCell;
00440
00441 goodDriftCut = 0.5 * cellWidth * M_SQRT2 + tkParam.pickHitMargin;
00442
00443 double deltaPhiCellWidth = 0.5 * (cellWidth * M_SQRT2)/layer->rMid();
00444
00445
00446 BesAngle phiTemp(0.0);
00447 int ierror = trk->projectToR(rEnter, phiTemp, hasCurled);
00448 phiEnter = phiTemp.posRad();
00449 if (ierror != 0) {
00450 if(6==tkParam.lPrint) std::cout<< " ErrMsg(warning) "
00451 << "Error in MdcTrackList::pickHits projection, ierror " <<ierror<< std::endl;
00452 continue;
00453 }
00454 ierror = trk->projectToR(rExit, phiTemp, hasCurled);
00455 phiExit = phiTemp.posRad();
00456 if (ierror != 0) {
00457 if(6==tkParam.lPrint) std::cout<< " ErrMsg(warning) "
00458 << "Error in MdcTrackList::pickHits projection, ierror "<<ierror << std::endl;
00459 continue;
00460 }
00461
00462
00463 if(6==tkParam.lPrint){
00464 std::cout<< endl<<"--pickHit of layer "<<layer->layNum()<<"--"<<std::endl;
00465 std::cout<< " track phiEnter "<< phiEnter.deg()<<" phiExit "<<phiExit.deg()<<" degree"<< std::endl;
00466 std::cout<< " cell width "<< 360./layer->nWires()<<" dPhiz "<<layer->dPhiz()*Constants::radToDegrees <<" deltaPhiCellWidth "<<0.5 * (cellWidth * M_SQRT2)/layer->rMid() * Constants::radToDegrees<<std::endl;
00467 std::cout<< " maxInactiveResid "<< tkParam.maxInactiveResid <<" pickHitPhiFactor "<<tkParam.pickHitPhiFactor<< std::endl;
00468 std::cout<< " goodDriftCut "<< goodDriftCut <<"=sqrt(2)*0.5*"<<cellWidth<<"+"<<tkParam.pickHitMargin<< std::endl;
00469 }
00470
00471 double Bz = trk->track().bField().bFieldZ();
00472
00473
00474 double t_phiHit = -999.;
00475 if (curv*Bz <= 0.0) {
00476
00477 phiLow = phiEnter;
00478 phiHigh = phiExit;
00479
00480 phiLow -= tkParam.maxInactiveResid / rEnter;
00481 phiHigh += tkParam.maxInactiveResid / rExit;
00482 } else {
00483 phiLow = phiExit;
00484 phiHigh = phiEnter;
00485 phiLow -= tkParam.maxInactiveResid / rExit;
00486 phiHigh += tkParam.maxInactiveResid / rEnter;
00487 }
00488
00489 if((phiHigh>0 && phiLow<0)){
00490 phiLow += Constants::twoPi;
00491 }else if((phiHigh<0 && phiLow>0)){
00492 phiHigh += Constants::twoPi;
00493 }
00494
00495 double lowFloat = nCell /Constants::twoPi * (phiLow - layer->phiOffset()) + 0.5;
00496 double highFloat = nCell /Constants::twoPi * (phiHigh - layer->phiOffset()) + 0.5;
00497 wireLow = (lowFloat >= 0.0) ? int(lowFloat) : int(floor(lowFloat));
00498 wireHigh = (highFloat >= 0.0) ? int(highFloat) : int(floor(highFloat));
00499
00500 if(6==tkParam.lPrint){
00501 std::cout << " wireLow "<<wireLow << " wireHigh "<<wireHigh <<" phiLow "<<phiLow*180./Constants::pi << " phiHigh "<<phiHigh*180./Constants::pi << std::endl;
00502 }
00503
00504 int tempDiff = 0;
00505 if(g_pickHitWire) {
00506 int tempN = Constants::maxCell[layer->layNum()];
00507 if(wireLow>tempN/2. && wireHigh<tempN/2.){
00508 g_pickHitWire->fill(wireHigh+tempN - wireLow);
00509 tempDiff = wireHigh+tempN - wireLow +1;
00510 }else{
00511 g_pickHitWire->fill(wireHigh - wireLow);
00512 tempDiff = wireHigh - wireLow +1;
00513 }
00514 }
00515
00516 if(wireLow>wireHigh) wireLow -= nCell;
00517 long t_iHit = 0;
00518 for (int thisWire = wireLow; thisWire <= wireHigh; thisWire++) {
00519 int corrWire = mdcWrapWire(thisWire, nCell);
00520 thisHit = map->hitWire(layer->layNum(), corrWire);
00521
00522 if(6==tkParam.lPrint){
00523 if(thisHit != 0) {cout<<endl<<"test hit "; thisHit->print(std::cout);}
00524 else std::cout << endl<<"test hit ("<<layer->layNum()<<","<<corrWire<<")"<< std::endl;
00525 }
00526
00527 double tof = 0.;
00528 double z = 0.;
00529 double driftDist = 0.;
00530
00531 double delx, dely;
00532 double resid = 0., predDrift = 0.;
00533 int ambig = 0;
00534 const MdcHitOnTrack *alink = 0;
00535 double mcTkId = -9999;
00536 if (thisHit == 0 ) {
00537 delx = -d0 * sinPhi0 - layer->xWire(corrWire);
00538 dely = d0 * cosPhi0 - layer->yWire(corrWire);
00539 predDrift = cosPhi0 * dely - sinPhi0 * delx +
00540 curv * (delx * delx + dely * dely);
00541 if(6==tkParam.lPrint) cout<<"No hit. predDrift="<<predDrift<<endl;
00542 continue;
00543 } else {
00544 if(m_tuplePick) mcTkId = thisHit->digi()->getTrackIndex();
00545
00546 if(thisHit->getHitOnTrack(&(trk->track())) ==0){
00547 alink = 0;
00548 }else{
00549 alink = thisHit->getHitOnTrack(&(trk->track()))->mdcHitOnTrack();
00550 if(6==tkParam.lPrint) { cout << " existing hot; " ;}
00551 }
00552
00553 if (alink == 0 || pickAm) {
00554 if ((!tkStatus->is2d()) && layer->view() != 0){
00555 double rc = 9999.;
00556 if(fabs(par.omega())>Constants::epsilon) rc = 1./fabs(par.omega());
00557 double rw = layer->rMid();
00558 double alpha = acos(1 - rw*rw/(2*rc*rc));
00559 double fltLen = rw;
00560 if(fabs(1 - rw*rw/(2*rc*rc))<1) fltLen = rc * alpha;
00561 z = par.z0() + fltLen* par.tanDip();
00562 tof = fltLen / Constants::c;
00563 double x = layer->getWire(corrWire)->xWireDC(z);
00564 double y = layer->getWire(corrWire)->yWireDC(z);
00565 delx = -d0 * sinPhi0 - x;
00566 dely = d0 * cosPhi0 - y;
00567 if(m_tuplePick) t_phiHit = thisHit->phi(z);
00568 }else{
00569 delx = -d0 * sinPhi0 - thisHit->x();
00570 dely = d0 * cosPhi0 - thisHit->y();
00571 if(m_tuplePick) t_phiHit = thisHit->phi();
00572 }
00573 predDrift = cosPhi0 * dely - sinPhi0 * delx +
00574 curv * (delx * delx + dely * dely);
00575
00576
00577 ambig = (predDrift >= 0) ? 1 : -1;
00578 if (hasCurled) ambig = -ambig;
00579 double entranceAngle=0.;
00580 driftDist = thisHit->driftDist(tof+bunchTime,ambig,entranceAngle,0.,z);
00581 if (alink == 0) {
00582
00583 resid = ambig * fabs(driftDist) - predDrift;
00584 aresid = fabs(resid);
00585
00586 }
00587 } else {
00588 ambig = alink->ambig();
00589 if(6==tkParam.lPrint) cout << " pick ambig for hot"<<endl;
00590 if(m_tuplePick) t_phiHit = par.phi0()+par.omega()*alink->fltLen();
00591 }
00592 }
00593
00594
00595 double zGuess = par.z0() + layer->rMid() * par.tanDip();
00596 double phiDCz = layer->getWire(corrWire)->phiDC(zGuess);
00597 BesAngle phiDCzMax(phiDCz + deltaPhiCellWidth);
00598 BesAngle phiDCzMin(phiDCz - deltaPhiCellWidth);
00599
00600 if(m_tuplePick && alink==0) {
00601 double sigma = 999.;
00602 if (thisHit != 0 &&alink==0) {
00603 double entranceAngle = 0.;
00604 sigma = thisHit->sigma(driftDist, ambig, entranceAngle, atan(par.tanDip()), z);
00605 }
00606 m_pickPredDrift[t_iHit] = predDrift;
00607 m_pickDrift[t_iHit] = driftDist;
00608 m_pickDriftTruth[t_iHit] = haveDigiDrift[thisHit->layernumber()][thisHit->wirenumber()];
00609 if(curv*Bz<=0.){
00610
00611 if((phiDCzMin-phiExit>0) || (phiDCzMax-phiEnter<0)) m_pickPhizOk[t_iHit] = 0;
00612 else m_pickPhizOk[t_iHit] = 1;
00613 }else{
00614 if((phiDCzMin-phiEnter>0) || (phiDCzMax-phiExit<0)) m_pickPhizOk[t_iHit] = 0;
00615 else m_pickPhizOk[t_iHit] = 1;
00616 }
00617 m_pickZ[t_iHit] = z;
00618 m_pickWire[t_iHit]=thisHit->wirenumber();
00619 m_pickResid[t_iHit] = aresid;
00620 if(abs(sigma)>0.000001) m_pickSigma[t_iHit] = sigma;
00621 else m_pickSigma[t_iHit] = 999.;
00622 double t_phiLowCut=-999.;
00623 double t_phiHighCut= -999.;
00624 if(t_phiHit > -998.){
00625 t_phiLowCut = (phiEnter-t_phiHit)*rEnter;
00626 t_phiHighCut = (phiExit-t_phiHit)*rExit;
00627 }
00628 m_pickPhiLowCut[t_iHit] = t_phiLowCut;
00629 m_pickPhiHighCut[t_iHit] = t_phiHighCut;
00630 m_pickDriftCut[t_iHit] = goodDriftCut;
00631 m_pickMcTk[t_iHit] = mcTkId;
00632 m_pickPt[t_iHit] = tkFit->pt();
00633 m_pickCurv[t_iHit] = curv;
00634 t_iHit++;
00635 }
00636
00637 if(curv*Bz<=0.){
00638
00639 if((phiDCzMin-phiExit>0) || (phiDCzMax-phiEnter<0)) {
00640 if(6==tkParam.lPrint){ std::cout<<" CUT by phiDCz not in phi En Ex range, curv>=0"<<std::endl; }
00641 continue;
00642 }
00643 }else{
00644
00645 if((phiDCzMin-phiEnter>0) || (phiDCzMax-phiExit<0)) {
00646 if(6==tkParam.lPrint){ std::cout<<" CUT by phiDCz not in phi En Ex range, curv<0"<<std::endl; }
00647 continue;
00648 }
00649 }
00650
00651
00652
00653 if (ambig != 0 && fabs(predDrift) > goodDriftCut){
00654 if(6==tkParam.lPrint){cout<<" predDrift "<<predDrift<<">goodDriftCut "<<goodDriftCut<<endl;}
00655 continue;
00656 }
00657
00658
00659 if (ambig == 0 && fabs(predDrift) > goodDriftCut){
00660 if(6==tkParam.lPrint){
00661 cout<<" ambig==0 && |predDirft| "<<fabs(predDrift) <<"> goodDriftCut "<< goodDriftCut<<endl;
00662 cout<<" No good hit, but track near cell-edge " << endl;
00663 }
00664 continue;
00665 }
00666
00667
00668
00669 if (ambig != 0) {
00670
00671
00672 double entranceAngle = 0.;
00673 double sigma = thisHit->sigma(driftDist, ambig, entranceAngle, atan(par.tanDip()), z);
00674 double factor = tkParam.pickHitFactor;
00675
00676
00677 double residCut = tkParam.maxActiveSigma * factor * sigma;
00678
00679
00680
00681
00682 if (alink == 0 && (aresid <= residCut) ) {
00683 if(6==tkParam.lPrint){
00684 cout << " (2) New hit found " << endl;
00685 }
00686
00687 int isActive = 1;
00688
00689
00690
00691
00692
00693 MdcRecoHitOnTrack tempHot(*thisHit, ambig, bunchTime);
00694 tempHot.setActivity(isActive);
00695
00696 if (thisHit->usedHit()){
00697 tempHot.setUsability(false);
00698 if(6==tkParam.lPrint) std::cout<< " thisHit used, setUsability false " << std::endl;
00699 }
00700
00701 double flt = layer->rMid();
00702 if (hasCurled) flt = Constants::twoPi * rCurl - layer->rMid();
00703 flt += 0.000001 * (thisHit->x() + thisHit->y());
00704 tempHot.setFltLen(flt);
00705 if(6==tkParam.lPrint) {
00706 std::cout<< " aresid "<<aresid<<"<=residCut " <<residCut<<" nSig "<<aresid/sigma<< " nSigCut "<<(tkParam.maxActiveSigma*factor)<<" factor "<<factor<<" maxActiveSigma "<<tkParam.maxActiveSigma<<" tanDip "<<par.tanDip()<<std::endl;
00707 std::cout<< " Append Hot " << std::endl;
00708 }
00709 alink = (MdcHitOnTrack*) hitList->appendHot(&tempHot);
00710 }else{
00711 if(6==tkParam.lPrint){
00712 if(alink!=0){
00713 std::cout<< "Exist hot found"<<std::endl;
00714 }else if(aresid > residCut){
00715 thisHit->print(std::cout);
00716 std::cout<< " Drop hit. aresid "<<aresid<<">residCut " <<residCut<<" nSig "<<aresid/sigma<< " nSigCut "<<(tkParam.maxActiveSigma*factor)<<" factor "<<factor<<" maxActiveSigma "<<tkParam.maxActiveSigma<<" tanDip "<<par.tanDip()<<std::endl;
00717 }
00718 }
00719 }
00720 if (!localHistory.member(const_cast<MdcHitOnTrack*>(alink))) {
00721 localHistory.append(const_cast<MdcHitOnTrack*>(alink));
00722 if (hasCurled) trk->setHasCurled();
00723 nFound++;
00724 if(6==tkParam.lPrint) std::cout<<" nFound="<<nFound<<" nCand "<<nCand<<std::endl;
00725 if (layer == firstInputLayer && firstInputHit < 0) {
00726 firstInputHit = nCand;
00727 }
00728 } else {
00729 if(6==tkParam.lPrint) std::cout << "ErrMsg(warning) "<< "would have inserted identical HOT "
00730 "twice in history buffer" << std::endl;
00731 }
00732 }
00733
00734
00735 else if (ambig == 0 && reachedLastInput) {
00736 if(6==tkParam.lPrint) std::cout << "ambig==0 "<<std::endl;
00737 lContinue = false;
00738 int nSuccess = 0;
00739 int last = 8;
00740 if (nCand < 8) last = nCand;
00741 for (int i = 0; i < last; i++) {
00742 int j = nCand - 1 - i;
00743 if (localHistory[j] != 0) {
00744
00745 nSuccess++;
00746 }
00747 if (i == 2 && nSuccess >= 2) lContinue = true;
00748 if (i == 4 && nSuccess >= 3) lContinue = true;
00749 if (i == 7 && nSuccess >= 5) lContinue = true;
00750 if(6==tkParam.lPrint) cout <<i<< " (3) No hit found; if beyond known good region " << endl;
00751 if (lContinue) {
00752 if(6==tkParam.lPrint) std::cout<<" pickHits break by lContinue. i="<<i<<" nSuccess="<<nSuccess<< std::endl;
00753 break;
00754 }
00755 }
00756
00757 if(6==tkParam.lPrint) cout << " (3) No hit found; if beyond known good region " << endl;
00758
00759 if (!lContinue) {
00760
00761 break;
00762 }
00763 localHistory.append(0);
00764 }
00765
00766 nCand++;
00767
00768 if (ambig != 0 && reachedLastInput) {
00769 if (trk->hasCurled() == 0) {
00770 if (thisHit->layer()->rEnd() > trk->lastLayer()->rEnd()) {
00771 trk->setLastLayer(thisHit->layer());
00772 }
00773 }
00774 else {
00775 if (thisHit->layer()->rEnd() < trk->lastLayer()->rEnd()) {
00776 trk->setLastLayer(thisHit->layer());
00777 }
00778 }
00779 }
00780
00781 }
00782 if(t_iHit>0 && m_tuplePick) {
00783 m_pickNCell = tempDiff;
00784 m_pickNCellWithDigi = t_iHit;
00785 m_pickLayer = layer->layNum();
00786 m_pickIs2D = is2d;
00787 m_tuplePick->write();
00788 }
00789 if (!lContinue && reachedLastInput) {
00790
00791 break;
00792 }
00793 }
00794
00795
00796 bool lContinue = true;
00797 for (int ihit = firstInputHit; ihit >= 0; ihit--) {
00798 if (localHistory[ihit] != 0) {
00799 if (lContinue) {
00800
00801 const MdcHitOnTrack *mdcHit = localHistory[ihit]->mdcHitOnTrack();
00802 if (mdcHit != 0) {
00803 if (mdcHit->layer()->rEnd() < trk->firstLayer()->rEnd()) {
00804 trk->setFirstLayer(mdcHit->layer());
00805 }
00806 }
00807 continue;
00808 } else {
00809
00810 if(6==tkParam.lPrint){
00811 std::cout << " gap found; delete hits. ";
00812 }
00813 if (!localHistory[ihit]->isUsable()) {
00814 if(6==tkParam.lPrint){
00815 cout << "about to delete hit for unusable HOT:" << endl;
00816 localHistory[ihit]->print(std::cout);
00817 }
00818 hitList->removeHit(localHistory[ihit]->hit());
00819 }
00820 if(6==tkParam.lPrint){
00821 cout << " current contents of localHistory: "
00822 <<localHistory.length()<<"hot" << endl;
00823
00824
00825
00826 }
00827 nFound--;
00828 }
00829 }
00830 else if (localHistory[ihit] == 0) {
00831 if(6==tkParam.lPrint){ cout << " localHistory= 0 " << endl; }
00832 int nSuccess = 0;
00833 lContinue = false;
00834 int last = 8;
00835 if (nCand < 8) last = nCand;
00836 for (int i = 0; i < last; i++) {
00837 int j = ihit + 1 + i;
00838 if (localHistory[j] != 0) nSuccess++;
00839 if (i == 2 && nSuccess >= 2) lContinue = true;
00840 if (i == 4 && nSuccess >= 3) lContinue = true;
00841
00842 if (lContinue) break;
00843 }
00844 }
00845 }
00846 if(6==tkParam.lPrint){
00847 std::cout<< "nFound="<<nFound <<" < "<< tkParam.pickHitFract*nCand<<" pickHitFract? "<< tkParam.pickHitFract<<"*"<<nCand << std::endl;
00848 }
00849 if (nFound < tkParam.pickHitFract * nCand) nFound = 0;
00850 if(6==tkParam.lPrint){ cout << " localHistory= 0 " << endl; }
00851
00852 if(6==tkParam.lPrint || 3==tkParam.lPrint){
00853 cout << "After pickHits found " << nFound <<" hit(s)"<< endl;
00854 hitList->hotList().print(std::cout);
00855 std::cout<< std::endl;
00856 }
00857
00858 return nFound;
00859 }
00860
00861
00862 int
00863 MdcTrackList::finishHelix(MdcTrack& mdcTrk, const MdcHitMap* map, const
00864 MdcDetector* gm) {
00865
00866 int success = 1;
00867
00868 TrkRecoTrk& trk = mdcTrk.track();
00869 TrkErrCode fitResult;
00870 TrkHelixMaker helMaker;
00871 const TrkFit* tkFit = trk.fitResult();
00872 assert (tkFit != 0);
00873 TrkHitList* hitList = trk.hits();
00874 assert (hitList != 0);
00875 TrkExchangePar par = tkFit->helix(0.0);
00876
00877
00878 helMaker.setFlipAndDrop(trk, true, true);
00879 fitResult = hitList->fit();
00880
00881 if (!fitResult.success() && (3 == tkParam.lPrint)) {
00882 cout << "Helix fit failure: " << endl;
00883 fitResult.print(cout);
00884 }
00885 helMaker.setFlipAndDrop(trk, false, false);
00886
00887 if (!fitResult.success()) return 0;
00888
00889 bool lcurler(fabs(tkFit->helix(0).omega()) > 3.4);
00890 pickHits(&mdcTrk, map, gm, lcurler);
00891
00892 if(3==tkParam.lPrint) std::cout<< __FILE__ << " " << __LINE__ << " nHit after pickHit "<<hitList->nHit() <<std::endl;
00893 if(3==tkParam.lPrint) hitList->hotList().printAll(std::cout);
00894
00895
00896 helMaker.setFlipAndDrop(trk, true, true);
00897 fitResult = hitList->fit();
00898 if (fitResult.failure()) {
00899 if(3==tkParam.lPrint){
00900 cout << "Second helix fit failed: " << endl;
00901 fitResult.print(std::cout);
00902 }
00903 return 0;
00904 }
00905 if(3==tkParam.lPrint){ cout << "Final fit: " << endl << trk << endl; }
00906 helMaker.setFlipAndDrop(trk, false, false);
00907
00908 double chisqperDOF = 0.;
00909 int nACT = tkFit->nActive();
00910 int nDOF = nACT - 5;
00911 if (nDOF > 5) {
00912 chisqperDOF = tkFit->chisq() / nDOF;
00913 } else {
00914 chisqperDOF = tkFit->chisq();
00915 }
00916 if(g_3dTkChi2) { g_3dTkChi2->fill( chisqperDOF ); }
00917 if(g_fitNAct) { g_fitNAct->fill(nACT ); }
00918
00919 int goodMatch = 1;
00920 if (fitResult.failure() || chisqperDOF > tkParam.maxChisq || nACT < tkParam.minHits ) {
00921 goodMatch = 0;
00922 if (3 == tkParam.lPrint) {
00923 std::cout<<" goodMatch=0; chi2/dof "<<chisqperDOF <<" >?maxChisq"<<tkParam.maxChisq
00924 <<" nAct:"<<nACT <<"<?minHits"<<tkParam.minHits << std::endl;
00925 }
00926 }
00927
00929
00930
00931
00932
00933
00934
00935
00936
00937 if (goodMatch) {
00938 if(3 <= m_debug){std::cout<<" ***** finishHelix success!"<< std::endl;}
00939 trk.fitResult()->positionErr(0.0);
00940 } else {
00941 success = 0;
00942 if(3 <= m_debug){std::cout<<" ***** finishHelix failure!"<< std::endl;}
00943 }
00944
00945 return success;
00946 }
00947
00948
00949
00950 int
00951 MdcTrackList::finishCircle(MdcTrack& mdcTrk, const MdcHitMap* map, const
00952 MdcDetector* gm) {
00953
00954 TrkRecoTrk& trk = mdcTrk.track();
00955 if(9==tkParam.lPrint){
00956 std::cout << " finishCircle "<< std::endl;
00957 trk.print(std::cout);
00958 }
00959
00960 const TrkFit* tkFit = trk.fitResult();
00961 if(9==tkParam.lPrint){ cout << "Before circle fit, nactive " << tkFit->nActive() << endl;}
00962 assert (tkFit != 0);
00963 TrkHitList* hitList = trk.hits();
00964 assert (hitList != 0);
00965 TrkCircleMaker circMaker;
00966 circMaker.setFlipAndDrop(trk, false, false);
00967
00968
00969 TrkErrCode fitResult = hitList->fit();
00970 if (fitResult.failure()) {
00971 trk.status()->addHistory(TrkErrCode(TrkErrCode::fail,15,"finishCircle"),"MdcTrkRecon");
00972 if (tkParam.lPrint > 1) {
00973 cout << "First circle fit failed: " << endl;
00974 fitResult.print(std::cout);
00975 }
00976 return 0;
00977 }
00978 trk.status()->addHistory(TrkErrCode(TrkErrCode::succeed,15,"finishCircle"),"MdcTrkRecon");
00979
00980 if(9==tkParam.lPrint){ cout << "After circle fit, nactive " << tkFit->nActive() << endl;}
00981 double chisqperDOF;
00982 int nDOF = tkFit->nActive() - 3;
00983 if (nDOF > 3){
00984 chisqperDOF = tkFit->chisq() / nDOF;
00985 }else{
00986 chisqperDOF = tkFit->chisq();
00987 }
00988
00989 if(g_cirTkChi2) { g_cirTkChi2->fill( chisqperDOF ); }
00990 int success = (chisqperDOF <= tkParam.maxChisq && tkFit->nActive() >= 3);
00991
00992 if(9==tkParam.lPrint){
00993 std::cout<<__FILE__<<" "<<__LINE__
00994 << " success "<<success
00995 << " chisqperDOF "<< chisqperDOF<<"<? maxChisq "<< tkParam.maxChisq
00996 << " nAct "<<tkFit->nActive()<<">=3 "
00997 << std::endl;
00998 mdcTrk.track().hots()->printAll(std::cout);
00999 }
01000 bool lcurler(fabs(tkFit->helix(0).omega()) > 3.4);
01001 pickHits(&mdcTrk, map, gm, lcurler);
01002
01003 if(9==tkParam.lPrint){
01004 std::cout<< __FILE__ << " " << __LINE__ << " nHit after pickHit "<<hitList->nHit() <<std::endl;
01005 }
01006
01007
01008 circMaker.setFlipAndDrop(trk, true, true);
01009 fitResult = hitList->fit();
01010 if (fitResult.failure()) {
01011 if(9==tkParam.lPrint){
01012 cout << "Second circle fit failed: " << endl;
01013 fitResult.print(std::cout);
01014 }
01015 return 0;
01016 }
01017 if(9==tkParam.lPrint){
01018 cout << "Final fit: " << endl << trk << endl;
01019 }
01020 circMaker.setFlipAndDrop(trk, false, false);
01021
01022 nDOF = tkFit->nActive() - 3;
01023 if (nDOF > 3) {
01024 chisqperDOF = tkFit->chisq() / nDOF;
01025 }
01026 else {
01027 chisqperDOF = tkFit->chisq();
01028 }
01029 if(g_cirTkChi2) { g_cirTkChi2->fill( chisqperDOF ); }
01030 success = (chisqperDOF <= tkParam.maxChisq) && (tkFit->nActive() >= 3);
01031
01032 if(9==tkParam.lPrint){
01033 cout << "chisqperDOF "<<chisqperDOF<<"=?" << tkParam.maxChisq<< endl;
01034 cout << "nActive "<<tkFit->nActive()<<">= 3"<< endl;
01035 }
01036
01037 if(9==tkParam.lPrint){
01038 trk.printAll(cout);
01039 }
01040
01041 return success;
01042 }
01043
01044 void MdcTrackList::dumpAxFill(const MdcTrack * trialTrack ) {
01045 std::cout << "ax fill: "<<std::endl;
01046 if(!trialTrack){
01047 trialTrack->track().printAll(cout);
01048 }
01049 }
01050
01051 void MdcTrackList::dumpSeed(const MdcSeg * seed,bool goodOnly ) {
01052 std::cout << std::endl<<"Dump seed segment goodOnly="<<goodOnly<<" ";
01053 seed->plotSegAll();
01054 std::cout<< std::endl;
01055 }
01056
01057 void MdcTrackList::dumpAxCombine(const MdcTrack * trialTrack) {
01058 if (NULL == trialTrack) return;
01059 std::cout<<std::endl<< "-------------------------------------"<<std::endl;
01060 std::cout<<"Track and hitList after AxCombine "<<std::endl;
01061 trialTrack->track().printAll(cout);
01062 TrkHotList::hot_iterator hotIter= trialTrack->track().hits()->hotList().begin();
01063 while (hotIter!=trialTrack->track().hits()->hotList().end()) {
01064 cout <<"(" <<((MdcHit*)(hotIter->hit()))->layernumber()
01065 <<","<<((MdcHit*)(hotIter->hit()))->wirenumber()
01066 <<":"<<hotIter->isActive()<<") ";
01067 hotIter++;
01068 }
01069 std::cout << std::endl;
01070 std::cout<< "-------------------------------------"<<std::endl;
01071 }
01072
01073 void MdcTrackList::dumpCircle(const MdcTrack* trialTrack ){
01074 if(NULL == trialTrack) return;
01075 if (!trialTrack->track().fitResult()) return;
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087 std::cout<<std::endl<< "-------------------------------------"<<std::endl;
01088 std::cout << "Track and hitList after finishCircle" << std::endl;
01089 trialTrack->track().printAll(cout);
01090 TrkHotList::hot_iterator hotIter= trialTrack->track().hits()->hotList().begin();
01091 while (hotIter!=trialTrack->track().hits()->hotList().end()) {
01092 cout <<"(" <<((MdcHit*)(hotIter->hit()))->layernumber()
01093 <<","<<((MdcHit*)(hotIter->hit()))->wirenumber()
01094 <<":"<<hotIter->isActive()<<") ";
01095 hotIter++;
01096 }
01097 cout <<endl;
01098 std::cout<< "-------------------------------------"<<std::endl;
01099 }
01100
01101 void MdcTrackList::dumpD0(const TrkExchangePar & par) {
01102
01103
01104
01105
01106 std::cout <<std::endl<< " Dump d0() " << par.d0()<<"\n";
01107
01108
01109 }
01110 void MdcTrackList::dumpStFill() {
01111 std::cout << "Plot segs after st fillWithSegs " << std::endl;
01112 cout <<endl;
01113
01114 }
01115
01116 void MdcTrackList::dumpStCombine(const MdcTrack * trialTrack) {
01117 std::cout<<std::endl<< "-------------------------------------"<<std::endl;
01118 std::cout<<"Track and hitList after StCombine "<<std::endl;
01119 if(trialTrack)trialTrack->track().printAll(cout);
01120 TrkHotList::hot_iterator hotIter= trialTrack->track().hits()->hotList().begin();
01121 int tmplay = -1;
01122 while (hotIter!=trialTrack->track().hits()->hotList().end()) {
01123 int layer = ((MdcHit*)(hotIter->hit()))->layernumber();
01124 if( (layer%4) ==0 ) { if( tmplay != layer ) cout<<endl; }
01125 cout <<"(" <<layer <<","<<((MdcHit*)(hotIter->hit()))->wirenumber()
01126 <<" act:"<<hotIter->isActive() <<" lr:"<<hotIter->ambig() <<") ";
01127 hotIter++;
01128 tmplay=layer;
01129 }
01130 cout <<endl;
01131 std::cout<< "-------------------------------------"<<std::endl;
01132 }
01133 void MdcTrackList::dumpHelix(const MdcTrack * trialTrack){
01134 std::cout<< std::endl<<"-------------------------------------"<<std::endl;
01135 std::cout<< "Track and hitList after finishHelix " << std::endl;
01136 trialTrack->track().printAll(cout);
01137 TrkHotList::hot_iterator hotIter= trialTrack->track().hits()->hotList().begin();
01138 int tmplay = -1;
01139 while (hotIter!=trialTrack->track().hits()->hotList().end()) {
01140 int layer = ((MdcHit*)(hotIter->hit()))->layernumber();
01141 if( (layer%4) ==0 ) { if( tmplay != layer ) cout<<endl; }
01142 cout <<"(" <<layer <<","<<((MdcHit*)(hotIter->hit()))->wirenumber()
01143 <<":"<<hotIter->isActive() <<") ";
01144 hotIter++;
01145 tmplay = layer;
01146 }
01147 cout <<endl;
01148 std::cout<< "-------------------------------------"<<std::endl;
01149 }
01150
01151 void MdcTrackList::dropMultiHotInLayer(const MdcTrack* tk){
01152 double tdr[43];
01153 double tdr_wire[43];
01154 for(int i=0; i<43; i++){tdr[i]=9999.;}
01155
01156
01157 TrkHotList::hot_iterator hotIter= tk->track().hits()->hotList().begin();
01158 while (hotIter!=tk->track().hits()->hotList().end()) {
01159 MdcHitOnTrack* hot = const_cast<MdcHitOnTrack*> (&(*hotIter->mdcHitOnTrack()));
01160
01161
01162 double dt = hot->mdcHit()->driftTime(0.,0.);
01163 int layer = hot->mdcHit()->layernumber();
01164 int wire = hot->mdcHit()->wirenumber();
01165 if (dt < tdr[layer]) {
01166 tdr[layer] = dt;
01167 tdr_wire[layer] = wire;
01168 }
01169 hotIter++;
01170 }
01171
01172 std::cout<<" tdr wire ";
01173 for(int i=0;i<43;i++){
01174 std::cout<<i<<" "<<tdr[i]<<" "<<tdr_wire<<" ";
01175 }
01176 std::cout<<" "<< std::endl;
01177
01178 hotIter= tk->track().hits()->hotList().begin();
01179 while (hotIter!=tk->track().hits()->hotList().end()) {
01180 int layer = hotIter->mdcHitOnTrack()->mdcHit()->layernumber();
01181 int wire = hotIter->mdcHitOnTrack()->mdcHit()->wirenumber();
01182 double dt = hotIter->mdcHitOnTrack()->mdcHit()->driftTime(0.,0.);
01183
01184 if ((tdr[layer] <9998.) && (tdr_wire[layer]!=wire)){
01185 MdcHitOnTrack* hot = const_cast<MdcHitOnTrack*> (&(*hotIter->mdcHitOnTrack()));
01186 hot->setActivity(false);
01187
01188 std::cout<<__FILE__<<" inactive "<< layer<<" "<<wire<<" dt "<<dt << std::endl;
01189 }
01190 hotIter++;
01191 }
01192 }