00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00260
00261
00262
00264
00347 #include "StMagUtilities.h"
00348 #include "TFile.h"
00349 #include "TCanvas.h"
00350 #include "TGraph.h"
00351 #include "TGraphErrors.h"
00352 #include "TF1.h"
00353 #include "TH2.h"
00354 #include "StTpcDb/StTpcDb.h"
00355 #include "tables/St_MagFactor_Table.h"
00356 #include "tables/St_tpcFieldCageShort_Table.h"
00357 #include "StDetectorDbMaker/St_tpcHVPlanesC.h"
00358 #include "StDetectorDbMaker/St_tpcAnodeHVavgC.h"
00359 #include "StDetectorDbMaker/St_tpcFieldCageShortC.h"
00360
00361
00362 static EBField gMap = kUndefined ;
00363 static Float_t gFactor = 1.0 ;
00364 static Float_t gRescale = 1.0 ;
00365 StMagUtilities *StMagUtilities::fgInstance = 0 ;
00366 static const Float_t PiOver12 = TMath::Pi()/12. ;
00367 static const Float_t PiOver6 = TMath::Pi()/6. ;
00368
00369
00370
00371
00372 ClassImp(StMagUtilities)
00373
00374
00375 StMagUtilities::StMagUtilities ()
00376 {
00377 cout << "StMagUtilities:: Unfortunately, instantiation with StMagUtilities(<empty>) is obsolete" << endl ;
00378 cout << "StMagUtilities:: You must specify DataBase pointers or specify the requested Field settings manually" << endl ;
00379 }
00380
00381
00383 StMagUtilities::StMagUtilities ( StTpcDb* dbin , TDataSet* dbin2, Int_t mode )
00384 {
00385 if (fgInstance) {
00386 cout << "ReInstate StMagUtilities. Be sure that this is want you want !" << endl;
00387 SafeDelete(fgInstance);
00388 }
00389 fgInstance = this;
00390 gMap = kMapped ;
00391 SetDb ( dbin, dbin2 ) ;
00392 GetMagFactor() ;
00393 GetTPCParams() ;
00394 GetTPCVoltages() ;
00395 GetOmegaTau () ;
00396 GetSpaceCharge() ;
00397 GetSpaceChargeR2() ;
00398 GetShortedRing() ;
00399 GetGridLeak() ;
00400 GetHVPlanes() ;
00401 CommonStart( mode ) ;
00402 UseManualSCForPredict(kFALSE) ;
00403 }
00404
00405
00407 StMagUtilities::StMagUtilities ( const EBField map, const Float_t factor, Int_t mode )
00408 {
00409 if (fgInstance) {
00410 cout << "ReInstate StMagUtilities. Be sure that this is want you want !" << endl;
00411 SafeDelete(fgInstance);
00412 }
00413 fgInstance = this;
00414 gMap = map ;
00415 thedb2 = 0 ;
00416 thedb = 0 ;
00417 gFactor = factor ;
00418 fTpcVolts = 0 ;
00419 fOmegaTau = 0 ;
00420 ManualSpaceCharge(0) ;
00421 ManualSpaceChargeR2(0,1) ;
00422 ManualShortedRing(0,0,0,0,0) ;
00423 fGridLeak = 0 ;
00424 fHVPlanes = 0 ;
00425 CommonStart( mode ) ;
00426 UseManualSCForPredict(kFALSE) ;
00427
00428 }
00429
00430
00431
00432
00433
00434 void StMagUtilities::SetDb ( StTpcDb* dbin , TDataSet* dbin2 )
00435 {
00436 thedb = dbin ;
00437 thedb2 = dbin2 ;
00438 }
00439
00440 void StMagUtilities::GetMagFactor ()
00441 {
00442 St_MagFactor *fMagFactor = (St_MagFactor *) thedb2->Find("MagFactor"); assert(fMagFactor) ;
00443 gFactor = (*fMagFactor)[0].ScaleFactor ;
00444
00445
00446
00447
00448
00449 }
00450
00451 void StMagUtilities::GetTPCParams ()
00452 {
00453 StarDriftV = 1e-6*thedb->DriftVelocity() ;
00454 TPC_Z0 = thedb->PadPlaneGeometry()->outerSectorPadPlaneZ() -
00455 thedb->WirePlaneGeometry()->outerSectorGatingGridPadPlaneSeparation() ;
00456 XTWIST = 1e3*thedb->GlobalPosition()->TpcEFieldRotationY() ;
00457 YTWIST = -1e3*thedb->GlobalPosition()->TpcEFieldRotationX() ;
00458 IFCShift = thedb->FieldCage()->InnerFieldCageShift();
00459 EASTCLOCKERROR = 1e3*thedb->FieldCage()->EastClockError();
00460 WESTCLOCKERROR = 1e3*thedb->FieldCage()->WestClockError();
00461 }
00462
00463 void StMagUtilities::GetTPCVoltages ()
00464 {
00465 fTpcVolts = StDetectorDbTpcVoltages::instance() ;
00466 CathodeV = fTpcVolts->getCathodeVoltage() * 1000 ;
00467 GG = fTpcVolts->getGGVoltage() ;
00468 StarMagE = TMath::Abs((CathodeV-GG)/TPC_Z0) ;
00469 if (TMath::Abs(StarMagE) < 1e-6) {
00470 cout << "StMagUtilities ERROR **** Calculations fail with extremely small or zero primary E field:" << endl;
00471 cout << "StMagUtilities StarMagE = (CathodeV - GG) / TPC_Z0 = (" << CathodeV
00472 << " - " << GG << ") / " << TPC_Z0 << " = " << StarMagE << " V/cm" << endl;
00473 exit(1);
00474 }
00475 St_tpcAnodeHVavgC* anodeVolts = St_tpcAnodeHVavgC::instance() ;
00476
00477
00478
00479
00480
00481
00482
00483 double maxInner = 1170;
00484 double maxOuter = 1390;
00485 double stepsInner = 35;
00486 double stepsOuter = 45;
00487 TH1I innerVs("innerVs","innerVs",5,maxInner-3.5*stepsInner,maxInner+1.5*stepsInner);
00488 TH1I outerVs("outerVs","outerVs",5,maxOuter-3.5*stepsOuter,maxOuter+1.5*stepsOuter);
00489 for (Int_t i = 1 ; i < 25; i++ ) {
00490 innerVs.Fill(anodeVolts->voltagePadrow(i,13));
00491 outerVs.Fill(anodeVolts->voltagePadrow(i,14));
00492 }
00493 double cmnInner = innerVs.GetBinCenter(innerVs.GetMaximumBin());
00494 double cmnOuter = outerVs.GetBinCenter(outerVs.GetMaximumBin());
00495 cout << "StMagUtilities assigning common anode voltages as " << cmnInner << " , " << cmnOuter << endl;
00496 for (Int_t i = 1 ; i < 25; i++ ) {
00497 GLWeights[i] = ( ( TMath::Abs(anodeVolts->voltagePadrow(i,13) - cmnInner) < stepsInner/2. ) &&
00498 ( TMath::Abs(anodeVolts->voltagePadrow(i,14) - cmnOuter) < stepsOuter/2. ) ? 1 : -1 );
00499 }
00500
00501
00502 }
00503
00504 void StMagUtilities::GetSpaceCharge ()
00505 {
00506 fSpaceCharge = StDetectorDbSpaceCharge::instance() ;
00507 SpaceCharge = fSpaceCharge->getSpaceChargeCoulombs((double)gFactor) ;
00508 }
00509
00510 void StMagUtilities::GetSpaceChargeR2 ()
00511 {
00512 fSpaceChargeR2 = StDetectorDbSpaceChargeR2::instance() ;
00513 SpaceChargeR2 = fSpaceChargeR2->getSpaceChargeCoulombs((double)gFactor) ;
00514 SpaceChargeEWRatio = fSpaceChargeR2->getEWRatio() ;
00515 }
00516
00517 void StMagUtilities::GetShortedRing ()
00518 {
00519 St_tpcFieldCageShortC* shortedRingsChair = St_tpcFieldCageShortC::instance();
00520 ShortTableRows = (Int_t) shortedRingsChair->GetNRows() ;
00521 for ( Int_t i = 0 ; i < ShortTableRows ; i++)
00522 {
00523 if ( i >= 10 ) break ;
00524 Side[i] = (Int_t) shortedRingsChair->side(i) ;
00525 Cage[i] = (Int_t) shortedRingsChair->cage(i) ;
00526 Ring[i] = (Float_t) shortedRingsChair->ring(i) ;
00527 MissingResistance[i] = (Float_t) shortedRingsChair->MissingResistance(i) ;
00528 Resistor[i] = (Float_t) shortedRingsChair->resistor(i) ;
00529 }
00530 }
00531
00532 Bool_t StMagUtilities::UpdateShortedRing ()
00533 {
00534 static tpcFieldCageShort_st* shortsTable = 0;
00535
00536 St_tpcFieldCageShortC* shortedRingsChair = St_tpcFieldCageShortC::instance();
00537 tpcFieldCageShort_st* new_shortsTable = shortedRingsChair->Struct();
00538 Bool_t update = (new_shortsTable != shortsTable);
00539 if (update) { GetShortedRing(); shortsTable = new_shortsTable; }
00540 return update;
00541 }
00542
00544
00548 void StMagUtilities::ManualShortedRing ( Int_t EastWest, Int_t InnerOuter,
00549 Float_t RingNumber, Float_t MissingRValue, Float_t ExtraRValue )
00550 {
00551
00552 ShortTableRows = 1 ;
00553 Side[0] = EastWest ;
00554 Cage[0] = InnerOuter ;
00555 Ring[0] = RingNumber ;
00556 MissingResistance[0] = MissingRValue ;
00557 Resistor[0] = ExtraRValue ;
00558 if ( ( Side[0] + Cage[0] + Ring[0] + TMath::Abs(MissingResistance[0]) + TMath::Abs(Resistor[0]) ) == 0.0 ) ShortTableRows = 0 ;
00559
00560
00561
00562
00563
00564
00565 }
00566
00567 void StMagUtilities::GetOmegaTau ()
00568 {
00569 fOmegaTau = StDetectorDbTpcOmegaTau::instance();
00570 TensorV1 = fOmegaTau->getOmegaTauTensorV1();
00571 TensorV2 = fOmegaTau->getOmegaTauTensorV2();
00572 }
00573
00575
00590 Int_t StMagUtilities::GetSpaceChargeMode()
00591 {
00592 if (mDistortionMode & kSpaceCharge) {
00593 if (fSpaceCharge) return 10;
00594 else return 11;
00595 }
00596 if (mDistortionMode & kSpaceChargeR2) {
00597 if (fSpaceChargeR2) return 20;
00598 else return 21;
00599 }
00600 return 0;
00601 }
00602
00603 void StMagUtilities::GetGridLeak ()
00604 {
00605 fGridLeak = StDetectorDbGridLeak::instance() ;
00606 InnerGridLeakStrength = fGridLeak -> getGridLeakStrength ( kGLinner ) ;
00607 InnerGridLeakRadius = fGridLeak -> getGridLeakRadius ( kGLinner ) ;
00608 InnerGridLeakWidth = fGridLeak -> getGridLeakWidth ( kGLinner ) ;
00609 MiddlGridLeakStrength = fGridLeak -> getGridLeakStrength ( kGLmiddl ) ;
00610 MiddlGridLeakRadius = fGridLeak -> getGridLeakRadius ( kGLmiddl ) ;
00611 MiddlGridLeakWidth = fGridLeak -> getGridLeakWidth ( kGLmiddl ) ;
00612 OuterGridLeakStrength = fGridLeak -> getGridLeakStrength ( kGLouter ) ;
00613 OuterGridLeakRadius = fGridLeak -> getGridLeakRadius ( kGLouter ) ;
00614 OuterGridLeakWidth = fGridLeak -> getGridLeakWidth ( kGLouter ) ;
00615 }
00616
00617 void StMagUtilities::ManualGridLeakStrength (Double_t inner, Double_t middle, Double_t outer)
00618 {
00619 InnerGridLeakStrength = inner ;
00620 MiddlGridLeakStrength = middle ;
00621 OuterGridLeakStrength = outer ;
00622
00623
00624 }
00625
00626 void StMagUtilities::ManualGridLeakRadius (Double_t inner, Double_t middle, Double_t outer)
00627 {
00628 InnerGridLeakRadius = inner ;
00629 MiddlGridLeakRadius = middle ;
00630 OuterGridLeakRadius = outer ;
00631 }
00632
00633 void StMagUtilities::ManualGridLeakWidth (Double_t inner, Double_t middle, Double_t outer)
00634 {
00635 InnerGridLeakWidth = inner ;
00636 MiddlGridLeakWidth = middle ;
00637 OuterGridLeakWidth = outer ;
00638 }
00639
00640 void StMagUtilities::GetHVPlanes ()
00641 {
00642 fHVPlanes = St_tpcHVPlanesC::instance() ;
00643 tpcHVPlanes_st* HVplanes = fHVPlanes -> Struct();
00644 deltaVGGEast = HVplanes -> GGE_shift_z * StarMagE;
00645 deltaVGGWest = - HVplanes -> GGW_shift_z * StarMagE;
00646 }
00647
00648 void StMagUtilities::ManualGGVoltError (Double_t east, Double_t west)
00649 {
00650 deltaVGGEast = east;
00651 deltaVGGWest = west;
00652 }
00653
00654
00655
00656
00657
00658
00659
00660 Float_t StMagUtilities::eRList[EMap_nR] = { 48.0, 49.0,
00661 50.0, 52.0, 54.0, 56.0, 58.0, 60.0, 62.0, 64.0, 66.0, 68.0,
00662 70.0, 72.0, 74.0, 76.0, 78.0, 80.0, 82.0, 84.0, 86.0, 88.0,
00663 90.0, 92.0, 94.0, 96.0, 98.0, 100.0, 102.0, 104.0, 106.0, 108.0,
00664 110.0, 112.0, 114.0, 116.0, 118.0, 120.0, 122.0, 124.0, 126.0, 128.0,
00665 130.0, 132.0, 134.0, 136.0, 138.0, 140.0, 142.0, 144.0, 146.0, 148.0,
00666 150.0, 152.0, 154.0, 156.0, 158.0, 160.0, 162.0, 164.0, 166.0, 168.0,
00667 170.0, 172.0, 174.0, 176.0, 178.0, 180.0, 182.0, 184.0, 186.0, 188.0,
00668 190.0, 192.0, 193.0, 194.0, 195.0, 196.0, 197.0, 198.0, 199.0, 199.5 } ;
00669
00670 Float_t StMagUtilities::ePhiList[EMap_nPhi] = { 0.0000, 0.5236, 1.0472, 1.5708, 2.0944, 2.6180, 3.1416,
00671 3.6652, 4.1888, 4.7124, 5.2360, 5.7596, 6.2832 } ;
00672
00673 Float_t StMagUtilities::eZList[EMap_nZ] = { -208.5, -208.0, -207.0, -206.0, -205.0, -204.0, -202.0,
00674 -200.0, -198.0, -196.0, -194.0, -192.0, -190.0, -188.0, -186.0, -184.0, -182.0,
00675 -180.0, -178.0, -176.0, -174.0, -172.0, -170.0, -168.0, -166.0, -164.0, -162.0,
00676 -160.0, -158.0, -156.0, -154.0, -152.0, -150.0, -148.0, -146.0, -144.0, -142.0,
00677 -140.0, -138.0, -136.0, -134.0, -132.0, -130.0, -128.0, -126.0, -124.0, -122.0,
00678 -120.0, -118.0, -116.0, -114.0, -112.0, -110.0, -108.0, -106.0, -104.0, -102.0,
00679 -100.0, -98.0, -96.0, -94.0, -92.0, -90.0, -88.0, -86.0, -84.0, -82.0,
00680 -80.0, -78.0, -76.0, -74.0, -72.0, -70.0, -68.0, -66.0, -64.0, -62.0,
00681 -60.0, -58.0, -56.0, -54.0, -52.0, -50.0, -48.0, -46.0, -44.0, -42.0,
00682 -40.0, -38.0, -36.0, -34.0, -32.0, -30.0, -28.0, -26.0, -24.0, -22.0,
00683 -20.0, -18.0, -16.0, -14.0, -12.0, -10.0, -8.0, -6.0, -4.0, -2.0,
00684 -1.0, -0.5, -0.2, -0.1, -0.05, 0.05, 0.1, 0.2, 0.5, 1.0,
00685 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0,
00686 22.0, 24.0, 26.0, 28.0, 30.0, 32.0, 34.0, 36.0, 38.0, 40.0,
00687 42.0, 44.0, 46.0, 48.0, 50.0, 52.0, 54.0, 56.0, 58.0, 60.0,
00688 62.0, 64.0, 66.0, 68.0, 70.0, 72.0, 74.0, 76.0, 78.0, 80.0,
00689 82.0, 84.0, 86.0, 88.0, 90.0, 92.0, 94.0, 96.0, 98.0, 100.0,
00690 102.0, 104.0, 106.0, 108.0, 110.0, 112.0, 114.0, 116.0, 118.0, 120.0,
00691 122.0, 124.0, 126.0, 128.0, 130.0, 132.0, 134.0, 136.0, 138.0, 140.0,
00692 142.0, 144.0, 146.0, 148.0, 150.0, 152.0, 154.0, 156.0, 158.0, 160.0,
00693 162.0, 164.0, 166.0, 168.0, 170.0, 172.0, 174.0, 176.0, 178.0, 180.0,
00694 182.0, 184.0, 186.0, 188.0, 190.0, 192.0, 194.0, 196.0, 198.0, 200.0,
00695 202.0, 204.0, 205.0, 206.0, 207.0, 208.0, 208.5 } ;
00696
00697
00698
00699
00700
00701
00703 void StMagUtilities::CommonStart ( Int_t mode )
00704 {
00705
00706
00707 IFCRadius = 47.90 ;
00708 OFCRadius = 200.0 ;
00709 GAPRADIUS = 121.8 ;
00710 GAP13_14 = 1.595 ;
00711
00712
00713
00714 if ( thedb2 == 0 ) cout << "StMagUtilities::CommonSta WARNING -- Using manually selected BFIELD setting." << endl ;
00715 else cout << "StMagUtilities::CommonSta Magnetic Field scale factor is " << gFactor << endl ;
00716
00717 if ( thedb == 0 )
00718 {
00719 cout << "StMagUtilities::CommonSta ***NO TPC DB, Using default TPC parameters. You sure it is OK??? ***" << endl ;
00720 cout << "StMagUtilities::CommonSta ***NO TPC DB, Using default TPC parameters. You sure it is OK??? ***" << endl ;
00721 cout << "StMagUtilities::CommonSta ***NO TPC DB, Using default TPC parameters. You sure it is OK??? ***" << endl ;
00722 cout << "StMagUtilities::CommonSta ***NO TPC DB, Using default TPC parameters. You sure it is OK??? ***" << endl ;
00723 StarDriftV = 5.54 ;
00724 TPC_Z0 = 208.7 ;
00725 XTWIST = -0.165 ;
00726 YTWIST = 0.219 ;
00727 IFCShift = 0.0080 ;
00728 EASTCLOCKERROR = 0.0 ;
00729 WESTCLOCKERROR = -0.43 ;
00730 cout << "StMagUtilities::CommonSta WARNING -- Using hard-wired TPC parameters. " << endl ;
00731 }
00732 else cout << "StMagUtilities::CommonSta Using TPC parameters from DataBase. " << endl ;
00733
00734 if ( fTpcVolts == 0 )
00735 {
00736 CathodeV = -27950.0 ;
00737 GG = -115.0 ;
00738 StarMagE = TMath::Abs((CathodeV-GG)/TPC_Z0) ;
00739 for (Int_t i = 0 ; i < 25; i++ ) GLWeights[i] = 1;
00740 cout << "StMagUtilities::CommonSta WARNING -- Using manually selected TpcVoltages setting. " << endl ;
00741 }
00742 else cout << "StMagUtilities::CommonSta Using TPC voltages from the DB." << endl ;
00743
00744 if ( fOmegaTau == 0 )
00745 {
00746 TensorV1 = 1.35 ;
00747 TensorV2 = 1.10 ;
00748 cout << "StMagUtilities::CommonSta WARNING -- Using manually selected OmegaTau parameters. " << endl ;
00749 }
00750 else cout << "StMagUtilities::CommonSta Using OmegaTau parameters from the DB." << endl ;
00751
00752 if (fSpaceCharge) cout << "StMagUtilities::CommonSta Using SpaceCharge values from the DB." << endl ;
00753 else cout << "StMagUtilities::CommonSta WARNING -- Using manually selected SpaceCharge settings. " << endl ;
00754
00755 if (fSpaceChargeR2) cout << "StMagUtilities::CommonSta Using SpaceChargeR2 values from the DB." << endl ;
00756 else cout << "StMagUtilities::CommonSta WARNING -- Using manually selected SpaceChargeR2 settings. " << endl ;
00757
00758 if ( fGridLeak == 0 )
00759 {
00760 ManualGridLeakStrength(0.0,15.0,0.0);
00761 ManualGridLeakRadius(53.0,GAPRADIUS,195.0);
00762 ManualGridLeakWidth(0.0,3.0,0.0);
00763 cout << "StMagUtilities::CommonSta WARNING -- Using manually selected GridLeak parameters. " << endl ;
00764 }
00765 else cout << "StMagUtilities::CommonSta Using GridLeak parameters from the DB." << endl ;
00766
00767 if ( fHVPlanes == 0 )
00768 {
00769 ManualGGVoltError(0.0,0.0);
00770 cout << "StMagUtilities::CommonSta WARNING -- Using manually selected HV planes parameters. " << endl ;
00771 }
00772 else cout << "StMagUtilities::CommonSta Using HV planes parameters from the DB." << endl ;
00773
00774
00775
00776
00777
00778 mDistortionMode = mode;
00779 if ( !( mode & ( kBMap | kPadrow13 | kTwist | kClock | kMembrane | kEndcap | kIFCShift | kSpaceCharge | kSpaceChargeR2
00780 | kShortedRing | kFast2DBMap | kGridLeak | k3DGridLeak | kGGVoltError | kSectorAlign )))
00781 {
00782 mDistortionMode |= kFast2DBMap ;
00783 mDistortionMode |= kPadrow13 ;
00784 mDistortionMode |= kTwist ;
00785 mDistortionMode |= kClock ;
00786 mDistortionMode |= kIFCShift ;
00787 printf("StMagUtilities::CommonSta Default mode selection\n");
00788 }
00789 else printf("StMagUtilities::CommonSta Using mode option 0x%X\n",mode);
00790
00791 Float_t B[3], X[3] = { 0, 0, 0 } ;
00792 Float_t OmegaTau ;
00793
00794 ReadField() ;
00795 BField(X,B) ;
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 OmegaTau = -10.0 * B[2] * StarDriftV / StarMagE ;
00812
00813 Const_0 = 1. / ( 1. + TensorV2*TensorV2*OmegaTau*OmegaTau ) ;
00814 Const_1 = TensorV1*OmegaTau / ( 1. + TensorV1*TensorV1*OmegaTau*OmegaTau ) ;
00815 Const_2 = TensorV2*TensorV2*OmegaTau*OmegaTau / ( 1. + TensorV2*TensorV2*OmegaTau*OmegaTau ) ;
00816
00817 cout << "StMagUtilities::BField = " << B[2] << " kGauss at (0,0,0)" << endl ;
00818 cout << "StMagUtilities::DriftVel = " << StarDriftV << " cm/microsec" << endl ;
00819 cout << "StMagUtilities::TPC_Z0 = " << TPC_Z0 << " cm" << endl ;
00820 cout << "StMagUtilities::TensorV1+V2 = " << TensorV1 << " " << TensorV2 << endl ;
00821 cout << "StMagUtilities::OmegaTau1+2 = " << OmegaTau * TensorV1 << " " << OmegaTau * TensorV2 << endl ;
00822 cout << "StMagUtilities::XTWIST = " << XTWIST << " mrad" << endl ;
00823 cout << "StMagUtilities::YTWIST = " << YTWIST << " mrad" << endl ;
00824 cout << "StMagUtilities::SpaceCharge = " << SpaceCharge << " Coulombs/epsilon-nought" << endl ;
00825 cout << "StMagUtilities::SpaceChargeR2 = " << SpaceChargeR2 << " Coulombs/epsilon-nought" << " EWRatio = "
00826 << SpaceChargeEWRatio << endl ;
00827 cout << "StMagUtilities::IFCShift = " << IFCShift << " cm" << endl ;
00828 cout << "StMagUtilities::CathodeV = " << CathodeV << " volts" << endl ;
00829 cout << "StMagUtilities::GG = " << GG << " volts" << endl ;
00830 cout << "StMagUtilities::EastClock = " << EASTCLOCKERROR << " mrad" << endl;
00831 cout << "StMagUtilities::WestClock = " << WESTCLOCKERROR << " mrad" << endl;
00832 cout << "StMagUtilities::Side = " ;
00833 for ( Int_t i = 0 ; i < ShortTableRows ; i++ ) cout << Side[i] << " " ; cout << "Location of Short E=0 / W=1 " << endl;
00834 cout << "StMagUtilities::Cage = " ;
00835 for ( Int_t i = 0 ; i < ShortTableRows ; i++ ) cout << Cage[i] << " " ; cout << "Location of Short IFC = 0 / OFC = 1" << endl;
00836 cout << "StMagUtilities::Ring = " ;
00837 for ( Int_t i = 0 ; i < ShortTableRows ; i++ ) cout << Ring[i] << " " ; cout << "Rings - Location of Short counting from the CM" << endl;
00838 cout << "StMagUtilities::MissingOhms = " ;
00839 for ( Int_t i = 0 ; i < ShortTableRows ; i++ ) cout << MissingResistance[i] << " " ; cout << "MOhms Missing Resistance" << endl;
00840 cout << "StMagUtilities::CompResistor = " ;
00841 for ( Int_t i = 0 ; i < ShortTableRows ; i++ ) cout << Resistor[i] << " " ; cout << "MOhm Compensating Resistor Value" << endl;
00842 cout << "StMagUtilities::InnerGridLeak = " << InnerGridLeakStrength << " " << InnerGridLeakRadius << " " << InnerGridLeakWidth << endl;
00843 cout << "StMagUtilities::MiddlGridLeak = " << MiddlGridLeakStrength << " " << MiddlGridLeakRadius << " " << MiddlGridLeakWidth << endl;
00844 cout << "StMagUtilities::OuterGridLeak = " << OuterGridLeakStrength << " " << OuterGridLeakRadius << " " << OuterGridLeakWidth << endl;
00845 cout << "StMagUtilities::deltaVGG = " << deltaVGGEast << " V (east) : " << deltaVGGWest << " V (west)" << endl;
00846 cout << "StMagUtilities::GLWeights = " ;
00847 for ( Int_t i = 1 ; i < 25 ; i++ ) cout << GLWeights[i] << " " ; cout << endl;
00848
00849 }
00850
00851
00852
00853
00855 void StMagUtilities::BField( const Float_t x[], Float_t B[] )
00856 {
00857
00858 Float_t r, z, Br_value, Bz_value ;
00859
00860 z = x[2] ;
00861 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
00862
00863 if ( r != 0.0 )
00864 {
00865 Interpolate2DBfield( r, z, Br_value, Bz_value ) ;
00866 B[0] = Br_value * (x[0]/r) ;
00867 B[1] = Br_value * (x[1]/r) ;
00868 B[2] = Bz_value ;
00869 }
00870 else
00871 {
00872 Interpolate2DBfield( r, z, Br_value, Bz_value ) ;
00873 B[0] = Br_value ;
00874 B[1] = 0.0 ;
00875 B[2] = Bz_value ;
00876 }
00877
00878 }
00879
00880
00882 void StMagUtilities::B3DField( const Float_t x[], Float_t B[] )
00883 {
00884
00885 Float_t r, z, phi, Br_value, Bz_value, Bphi_value ;
00886
00887 z = x[2] ;
00888 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
00889
00890 if ( r != 0.0 )
00891 {
00892 phi = TMath::ATan2( x[1], x[0] ) ;
00893 if ( phi < 0 ) phi += 2*TMath::Pi() ;
00894 Interpolate3DBfield( r, z, phi, Br_value, Bz_value, Bphi_value ) ;
00895 B[0] = Br_value * (x[0]/r) - Bphi_value * (x[1]/r) ;
00896 B[1] = Br_value * (x[1]/r) + Bphi_value * (x[0]/r) ;
00897 B[2] = Bz_value ;
00898 }
00899 else
00900 {
00901 phi = 0 ;
00902 Interpolate3DBfield( r, z, phi, Br_value, Bz_value, Bphi_value ) ;
00903 B[0] = Br_value ;
00904 B[1] = Bphi_value ;
00905 B[2] = Bz_value ;
00906 }
00907
00908 return ;
00909
00910 }
00911
00912
00914 void StMagUtilities::BrBzField( const Float_t r, const Float_t z, Float_t &Br_value, Float_t &Bz_value )
00915 {
00916
00917 Interpolate2DBfield( r, z, Br_value, Bz_value ) ;
00918
00919 }
00920
00921
00923 void StMagUtilities::BrBz3DField( const Float_t r, const Float_t z, const Float_t phi,
00924 Float_t &Br_value, Float_t &Bz_value, Float_t &Bphi_value )
00925 {
00926
00927 Float_t phiprime ;
00928 phiprime = phi ;
00929 if ( phiprime < 0 ) phiprime += 2*TMath::Pi() ;
00930 Interpolate3DBfield( r, z, phiprime, Br_value, Bz_value, Bphi_value ) ;
00931
00932 }
00933
00934
00935
00936
00937
00939 void StMagUtilities::UndoDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
00940 {
00941
00942 Float_t Xprime1[3], Xprime2[3] ;
00943
00944 SectorNumber( Sector, x ) ;
00945
00946
00947 for (unsigned int i=0; i<3; ++i) {
00948 Xprime1[i] = x[i];
00949 }
00950
00951 Float_t r2 = x[0]*x[0] + x[1]*x[1] ;
00952 if ( r2 >= OFCRadius*OFCRadius || r2 <= IFCRadius*IFCRadius || x[2] >= TPC_Z0 || x[2] <= -1*TPC_Z0 )
00953 {
00954 for (unsigned int i=0; i<3; ++i) { Xprime[i] = x[i] ; }
00955 return ;
00956 }
00957
00958 if (mDistortionMode & kBMap) {
00959 FastUndoBDistortion ( Xprime1, Xprime2, Sector ) ;
00960 for (unsigned int i=0; i<3; ++i) {
00961 Xprime1[i] = Xprime2[i];
00962 }
00963 }
00964
00965 if (mDistortionMode & kFast2DBMap) {
00966 FastUndo2DBDistortion ( Xprime1, Xprime2, Sector ) ;
00967 for (unsigned int i=0; i<3; ++i) {
00968 Xprime1[i] = Xprime2[i];
00969 }
00970 }
00971
00972 if ((mDistortionMode & kBMap) && (mDistortionMode & kFast2DBMap)) {
00973 cout << "StMagUtilities ERROR **** Do not use kBMap and kFast2DBMap at the same time" << endl ;
00974 cout << "StMagUtilities ERROR **** These routines have duplicate functionality so don't do both." << endl ;
00975 exit(1) ;
00976 }
00977
00978
00979 if (mDistortionMode & kPadrow13) {
00980 UndoPad13Distortion ( Xprime1, Xprime2, Sector ) ;
00981 for (unsigned int i=0; i<3; ++i) {
00982 Xprime1[i] = Xprime2[i];
00983 }
00984 }
00985
00986 if (mDistortionMode & kTwist) {
00987
00988 UndoTwistDistortion ( Xprime1, Xprime2, Sector ) ;
00989 for (unsigned int i=0; i<3; ++i) {
00990 Xprime1[i] = Xprime2[i];
00991 }
00992 }
00993
00994 if (mDistortionMode & kClock) {
00995
00996 UndoClockDistortion ( Xprime1, Xprime2, Sector ) ;
00997 for (unsigned int i=0; i<3; ++i) {
00998 Xprime1[i] = Xprime2[i];
00999 }
01000 }
01001
01002 if (mDistortionMode & kMembrane) {
01003
01004 UndoMembraneDistortion ( Xprime1, Xprime2, Sector ) ;
01005 for (unsigned int i=0; i<3; ++i) {
01006 Xprime1[i] = Xprime2[i];
01007 }
01008
01009 }
01010
01011 if (mDistortionMode & kEndcap)
01012 {
01013 UndoEndcapDistortion ( Xprime1, Xprime2, Sector ) ;
01014 for (unsigned int i=0; i<3; ++i) {
01015 Xprime1[i] = Xprime2[i];
01016 }
01017 }
01018
01019 if (mDistortionMode & kIFCShift) {
01020 UndoIFCShiftDistortion ( Xprime1, Xprime2, Sector ) ;
01021 for (unsigned int i=0; i<3; ++i) {
01022 Xprime1[i] = Xprime2[i];
01023 }
01024 }
01025
01026 if (mDistortionMode & kSpaceCharge) {
01027 UndoSpaceChargeDistortion ( Xprime1, Xprime2, Sector ) ;
01028 for (unsigned int i=0; i<3; ++i) {
01029 Xprime1[i] = Xprime2[i];
01030 }
01031 }
01032
01033 if (mDistortionMode & kSpaceChargeR2) {
01034 UndoSpaceChargeR2Distortion ( Xprime1, Xprime2, Sector ) ;
01035 for (unsigned int i=0; i<3; ++i) {
01036 Xprime1[i] = Xprime2[i];
01037 }
01038 }
01039
01040 if ((mDistortionMode & kSpaceCharge) && (mDistortionMode & kSpaceChargeR2)) {
01041 cout << "StMagUtilities ERROR **** Do not use kSpaceCharge and kspaceChargeR2 at the same time" << endl ;
01042 cout << "StMagUtilities ERROR **** These routines have overlapping functionality." << endl ;
01043 exit(1) ;
01044 }
01045
01046 if (mDistortionMode & kShortedRing) {
01047 UndoShortedRingDistortion ( Xprime1, Xprime2, Sector ) ;
01048 for (unsigned int i=0; i<3; ++i) {
01049 Xprime1[i] = Xprime2[i];
01050 }
01051 }
01052
01053 if (mDistortionMode & kGridLeak) {
01054 UndoGridLeakDistortion ( Xprime1, Xprime2, Sector ) ;
01055 for (unsigned int i=0; i<3; ++i) {
01056 Xprime1[i] = Xprime2[i];
01057 }
01058 }
01059
01060 if (mDistortionMode & k3DGridLeak) {
01061 Undo3DGridLeakDistortion ( Xprime1, Xprime2, Sector ) ;
01062 for (unsigned int i=0; i<3; ++i) {
01063 Xprime1[i] = Xprime2[i];
01064 }
01065 }
01066
01067 if ((mDistortionMode & kGridLeak) && (mDistortionMode & k3DGridLeak)) {
01068 cout << "StMagUtilities ERROR **** Do not use kGridLeak and k3DGridLeak at the same time" << endl ;
01069 cout << "StMagUtilities ERROR **** These routines have overlapping functionality." << endl ;
01070 exit(1) ;
01071 }
01072
01073 if (mDistortionMode & kGGVoltError) {
01074 UndoGGVoltErrorDistortion ( Xprime1, Xprime2, Sector ) ;
01075 for (unsigned int i=0; i<3; ++i) {
01076 Xprime1[i] = Xprime2[i];
01077 }
01078 }
01079
01080 if (mDistortionMode & kSectorAlign) {
01081 UndoSectorAlignDistortion ( Xprime1, Xprime2, Sector ) ;
01082 for (unsigned int i=0; i<3; ++i) {
01083 Xprime1[i] = Xprime2[i];
01084 }
01085 }
01086
01087
01088
01089 for (unsigned int i=0; i<3; ++i) {
01090 Xprime[i] = Xprime1[i];
01091 }
01092
01093 }
01094
01095
01096
01097
01098
01100 void StMagUtilities::DoDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01101 {
01102
01103 UndoDistortion ( x, Xprime, Sector ) ;
01104
01105 Xprime[0] = 2*x[0] - Xprime[0] ;
01106 Xprime[1] = 2*x[1] - Xprime[1] ;
01107 Xprime[2] = 2*x[2] - Xprime[2] ;
01108
01109 }
01110
01111
01112
01113
01114
01116
01121 void StMagUtilities::UndoBDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01122 {
01123
01124 Double_t ah ;
01125 Float_t B[3] ;
01126 Int_t sign, index = 1 , NSTEPS ;
01127
01128 SectorNumber( Sector, x ) ;
01129 sign = ( Sector <= 12 ? 1 : -1 ) ;
01130
01131 Xprime[0] = x[0] ;
01132 Xprime[1] = x[1] ;
01133 Xprime[2] = sign * TPC_Z0 ;
01134
01135 for ( NSTEPS = 5 ; NSTEPS < 1000 ; NSTEPS += 2 )
01136 {
01137 ah = ( x[2] - sign * TPC_Z0 ) / ( NSTEPS - 1 ) ;
01138 if ( TMath::Abs(ah) < 1.0 ) break ;
01139 }
01140
01141 for ( Int_t i = 1; i <= NSTEPS; ++i )
01142 {
01143 if ( i == NSTEPS ) index = 1 ;
01144 Xprime[2] += index*(ah/3) ;
01145 B3DField( Xprime, B ) ;
01146 if ( TMath::Abs(B[2]) > 0.001 )
01147 {
01148 Xprime[0] += index*(ah/3)*( Const_2*B[0] - Const_1*B[1] ) / B[2] ;
01149 Xprime[1] += index*(ah/3)*( Const_2*B[1] + Const_1*B[0] ) / B[2] ;
01150 }
01151 if ( index != 4 ) index = 4; else index = 2 ;
01152 }
01153
01154 }
01155
01156
01158
01163 void StMagUtilities::Undo2DBDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01164 {
01165
01166 Double_t ah ;
01167 Float_t B[3] ;
01168 Int_t sign, index = 1 , NSTEPS ;
01169
01170 SectorNumber( Sector, x ) ;
01171 sign = ( Sector <= 12 ? 1 : -1 ) ;
01172
01173 Xprime[0] = x[0] ;
01174 Xprime[1] = x[1] ;
01175 Xprime[2] = sign * TPC_Z0 ;
01176
01177 for ( NSTEPS = 5 ; NSTEPS < 1000 ; NSTEPS += 2 )
01178 {
01179 ah = ( x[2] - sign * TPC_Z0 ) / ( NSTEPS - 1 ) ;
01180 if ( TMath::Abs(ah) < 1.0 ) break ;
01181 }
01182
01183 for ( Int_t i = 1; i <= NSTEPS; ++i )
01184 {
01185 if ( i == NSTEPS ) index = 1 ;
01186 Xprime[2] += index*(ah/3) ;
01187 BField( Xprime, B ) ;
01188 if ( TMath::Abs(B[2]) > 0.001 )
01189 {
01190 Xprime[0] += index*(ah/3)*( Const_2*B[0] - Const_1*B[1] ) / B[2] ;
01191 Xprime[1] += index*(ah/3)*( Const_2*B[1] + Const_1*B[0] ) / B[2] ;
01192 }
01193 if ( index != 4 ) index = 4; else index = 2 ;
01194 }
01195
01196 }
01197
01198
01200
01205 void StMagUtilities::FastUndoBDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01206 {
01207
01208 static Float_t dx3D[EMap_nPhi][EMap_nR][EMap_nZ], dy3D[EMap_nPhi][EMap_nR][EMap_nZ] ;
01209 static Int_t ilow = 0, jlow = 0, klow = 0 ;
01210 static Int_t DoOnce = 0 ;
01211 const Int_t PHIORDER = 1 ;
01212 const Int_t ORDER = 1 ;
01213
01214 Int_t i, j, k ;
01215 Float_t xx[3] ;
01216 Float_t save_x[ORDER+1], saved_x[ORDER+1] ;
01217 Float_t save_y[ORDER+1], saved_y[ORDER+1] ;
01218
01219 Float_t r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
01220 Float_t phi = TMath::ATan2(x[1],x[0]) ;
01221 if ( phi < 0 ) phi += TMath::TwoPi() ;
01222 Float_t z = LimitZ( Sector, x ) ;
01223
01224 if ( DoOnce == 0 )
01225 {
01226 cout << "StMagUtilities::FastUndoD Please wait for the tables to fill ... ~90 seconds" << endl ;
01227 for ( k = 0 ; k < EMap_nPhi ; k++ )
01228 {
01229 for ( i = 0 ; i < EMap_nR ; i++ )
01230 {
01231 xx[0] = eRList[i] * TMath::Cos(ePhiList[k]) ;
01232 xx[1] = eRList[i] * TMath::Sin(ePhiList[k]) ;
01233 for ( j = 0 ; j < EMap_nZ ; j++ )
01234 {
01235 xx[2] = eZList[j] ;
01236 UndoBDistortion(xx,Xprime) ;
01237 dx3D[k][i][j] = Xprime[0] - xx[0] ;
01238 dy3D[k][i][j] = Xprime[1] - xx[1] ;
01239 }
01240 }
01241 }
01242 DoOnce = 1 ;
01243 }
01244
01245 Search( EMap_nPhi, ePhiList, phi, klow ) ;
01246 Search( EMap_nR, eRList, r, ilow ) ;
01247 Search( EMap_nZ, eZList, z, jlow ) ;
01248 if ( klow < 0 ) klow = 0 ;
01249 if ( ilow < 0 ) ilow = 0 ;
01250 if ( jlow < 0 ) jlow = 0 ;
01251 if ( klow + ORDER >= EMap_nPhi-1 ) klow = EMap_nPhi - 1 - ORDER ;
01252 if ( ilow + ORDER >= EMap_nR-1 ) ilow = EMap_nR - 1 - ORDER ;
01253 if ( jlow + ORDER >= EMap_nZ-1 ) jlow = EMap_nZ - 1 - ORDER ;
01254
01255 for ( k = klow ; k < klow + ORDER + 1 ; k++ )
01256 {
01257 for ( i = ilow ; i < ilow + ORDER + 1 ; i++ )
01258 {
01259 save_x[i-ilow] = Interpolate( &eZList[jlow], &dx3D[k][i][jlow], ORDER, z ) ;
01260 save_y[i-ilow] = Interpolate( &eZList[jlow], &dy3D[k][i][jlow], ORDER, z ) ;
01261 }
01262 saved_x[k-klow] = Interpolate( &eRList[ilow], save_x, ORDER, r ) ;
01263 saved_y[k-klow] = Interpolate( &eRList[ilow], save_y, ORDER, r ) ;
01264 }
01265
01266 Xprime[0] = Interpolate( &ePhiList[klow], saved_x, PHIORDER, phi ) + x[0] ;
01267 Xprime[1] = Interpolate( &ePhiList[klow], saved_y, PHIORDER, phi ) + x[1];
01268
01269 Xprime[2] = x[2] ;
01270
01271 }
01272
01273
01275
01284 void StMagUtilities::FastUndo2DBDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01285 {
01286
01287 static Float_t dR[EMap_nR][EMap_nZ], dRPhi[EMap_nR][EMap_nZ] ;
01288 static Int_t ilow = 0, jlow = 0 ;
01289 static Int_t DoOnce = 0 ;
01290 const Int_t ORDER = 1 ;
01291
01292 Int_t i, j ;
01293 Float_t xx[3] ;
01294 Float_t save_dR[ORDER+1], saved_dR ;
01295 Float_t save_dRPhi[ORDER+1], saved_dRPhi ;
01296
01297 Float_t r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
01298 Float_t phi = TMath::ATan2(x[1],x[0]) ;
01299 if ( phi < 0 ) phi += TMath::TwoPi() ;
01300 Float_t z = LimitZ( Sector, x ) ;
01301
01302 if ( DoOnce == 0 )
01303 {
01304 cout << "StMagUtilities::FastUndo2 Please wait for the tables to fill ... ~5 seconds" << endl ;
01305 for ( i = 0 ; i < EMap_nR ; i++ )
01306 {
01307 xx[0] = eRList[i] ;
01308 xx[1] = 0 ;
01309 for ( j = 0 ; j < EMap_nZ ; j++ )
01310 {
01311 xx[2] = eZList[j] ;
01312 Undo2DBDistortion(xx,Xprime) ;
01313 dR[i][j] = Xprime[0] ;
01314 dRPhi[i][j] = Xprime[1] ;
01315 }
01316 }
01317 DoOnce = 1 ;
01318 }
01319
01320 Search( EMap_nR, eRList, r, ilow ) ;
01321 Search( EMap_nZ, eZList, z, jlow ) ;
01322 if ( ilow < 0 ) ilow = 0 ;
01323 if ( jlow < 0 ) jlow = 0 ;
01324 if ( ilow + ORDER >= EMap_nR-1 ) ilow = EMap_nR - 1 - ORDER ;
01325 if ( jlow + ORDER >= EMap_nZ-1 ) jlow = EMap_nZ - 1 - ORDER ;
01326
01327 for ( i = ilow ; i < ilow + ORDER + 1 ; i++ )
01328 {
01329 save_dR[i-ilow] = Interpolate( &eZList[jlow], &dR[i][jlow], ORDER, z ) ;
01330 save_dRPhi[i-ilow] = Interpolate( &eZList[jlow], &dRPhi[i][jlow], ORDER, z ) ;
01331 }
01332
01333 saved_dR = Interpolate( &eRList[ilow], save_dR, ORDER, r ) ;
01334 saved_dRPhi = Interpolate( &eRList[ilow], save_dRPhi, ORDER, r ) ;
01335
01336 if ( r > 0.0 )
01337 {
01338 r = saved_dR ;
01339 phi = phi + saved_dRPhi / r ;
01340 if ( phi < 0 ) phi += 2*TMath::Pi() ;
01341 }
01342
01343 Xprime[0] = r * TMath::Cos(phi) ;
01344 Xprime[1] = r * TMath::Sin(phi) ;
01345 Xprime[2] = x[2] ;
01346
01347 }
01348
01349
01350
01351
01352
01354
01359 void StMagUtilities::UndoTwistDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01360 {
01361
01362 Double_t Zdrift ;
01363 Int_t sign ;
01364
01365
01366
01367
01368 Float_t z = LimitZ( Sector, x ) ;
01369 sign = ( Sector <= 12 ? 1 : -1 ) ;
01370
01371 Zdrift = sign * ( TPC_Z0 - TMath::Abs(z) ) ;
01372 Xprime[0] = x[0] - ( Const_1 * YTWIST - Const_2 * XTWIST ) * Zdrift/1000 ;
01373 Xprime[1] = x[1] - ( -1* Const_1 * XTWIST - Const_2 * YTWIST ) * Zdrift/1000 ;
01374 Xprime[2] = x[2] ;
01375
01376 }
01377
01378
01379
01380
01381
01382 #define NYARRAY 37 // Dimension of the vector to contain the YArray
01383 #define NZDRIFT 19 // Dimension of the vector to contain ZDriftArray
01384
01386
01392 void StMagUtilities::UndoPad13Distortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01393 {
01394
01395 const Int_t ORDER = 2 ;
01396 const Int_t TERMS = 400 ;
01397 const Float_t SCALE = 0.192 ;
01398 const Float_t BOX = 200.0 - GAPRADIUS ;
01399 const Float_t PI = TMath::Pi() ;
01400
01401
01402
01403
01404
01405 static Float_t ZDriftArray[NZDRIFT] = {0,1,2,3,4,5,7.5,10,12.5,15,17.5,20,25,30,50,75,100,210,220} ;
01406
01407 static Float_t YArray[NYARRAY] = { 50.0, 75.0, 100.0,
01408 103.5, 104.0, 104.5,
01409 108.7, 109.2, 109.7,
01410 113.9, 114.4, 114.9,
01411 118.9, 119.6, 119.8,
01412 120.0, 120.25, 120.5, 120.75,
01413 121.0, 121.5, 122.1, 122.6,
01414 124.2, 125.2,
01415 126.2, 127.195,
01416 128.2, 129.195,
01417 130.2, 131.195,
01418 132.2, 133.195,
01419 137.195, 150.,
01420 198., 200. } ;
01421
01422 static Double_t C[TERMS] ;
01423 static Int_t DoOnce = 0 ;
01424 static Float_t SumArray[NZDRIFT][NYARRAY] ;
01425 static Int_t ilow = 0, jlow = 0 ;
01426
01427 Float_t y, z, Zdrift, save_sum[3] ;
01428 Double_t r, phi, phi0, sum = 0.0 ;
01429
01430 if ( DoOnce == 0 )
01431 {
01432 cout << "StMagUtilities::PadRow13 Please wait for the tables to fill ... ~5 seconds" << endl ;
01433 C[0] = GAP13_14 * GG * SCALE / ( 2 * BOX ) ;
01434 for ( Int_t i = 1 ; i < TERMS ; i++ )
01435 C[i] = 2 * GG * SCALE * TMath::Sin( GAP13_14*i*PI/( 2*BOX ) ) / ( i * PI ) ;
01436 for ( Int_t i = 0; i < NZDRIFT ; i++ )
01437 {
01438 Zdrift = ZDriftArray[i] ;
01439 for ( Int_t j = 0; j < NYARRAY ; j++ )
01440 {
01441 sum = 0.0 ;
01442 y = YArray[j] ;
01443 for ( Int_t k = 1 ; k < TERMS ; k++ )
01444 {
01445 sum += ( C[k] / StarMagE ) * ( 1. - TMath::Exp(-1*k*PI*Zdrift/BOX) )
01446 * TMath::Sin(k*PI*(y-GAPRADIUS)/BOX) ;
01447 }
01448 SumArray[i][j] = sum ;
01449 }
01450 }
01451 DoOnce = 1 ;
01452 }
01453
01454 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
01455 phi = TMath::ATan2(x[1],x[0]) ;
01456 phi0 = ( (Int_t)((TMath::Abs(phi)+PiOver12)/PiOver6 + 6.0 ) - 6.0 ) * PiOver6 ;
01457 if ( phi < 0 ) phi0 *= -1. ;
01458 y = r * TMath::Cos( phi0 - phi ) ;
01459 z = LimitZ( Sector, x ) ;
01460 Zdrift = TPC_Z0 - TMath::Abs(z) ;
01461
01462 Search ( NZDRIFT, ZDriftArray, Zdrift, ilow ) ;
01463 Search ( NYARRAY, YArray, y, jlow ) ;
01464
01465 if ( ilow < 0 ) ilow = 0 ;
01466 if ( jlow < 0 ) jlow = 0 ;
01467 if ( ilow + ORDER >= NZDRIFT - 1 ) ilow = NZDRIFT - 1 - ORDER ;
01468 if ( jlow + ORDER >= NYARRAY - 1 ) jlow = NYARRAY - 1 - ORDER ;
01469
01470 for ( Int_t i = ilow ; i < ilow + ORDER + 1 ; i++ )
01471 {
01472 save_sum[i-ilow] = Interpolate( &YArray[jlow], &SumArray[i][jlow], ORDER, y ) ;
01473 }
01474
01475 sum = Interpolate( &ZDriftArray[ilow], save_sum, ORDER, Zdrift ) ;
01476
01477 if ( r > 0.0 )
01478 {
01479 phi = phi - ( Const_1*(-1*sum)*TMath::Cos(phi0-phi) + Const_0*sum*TMath::Sin(phi0-phi) ) / r ;
01480 r = r - ( Const_0*sum*TMath::Cos(phi0-phi) - Const_1*(-1*sum)*TMath::Sin(phi0-phi) ) ;
01481 }
01482
01483 Xprime[0] = r * TMath::Cos(phi) ;
01484 Xprime[1] = r * TMath::Sin(phi) ;
01485 Xprime[2] = x[2] ;
01486
01487 }
01488
01489
01490
01491
01492
01494
01503 void StMagUtilities::UndoClockDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01504 {
01505
01506 Double_t r, phi, z ;
01507
01508 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
01509 phi = TMath::ATan2(x[1],x[0]) ;
01510
01511 z = LimitZ( Sector, x ) ;
01512
01513 if ( z < 0 ) phi += EASTCLOCKERROR/1000. ;
01514 if ( z > 0 ) phi += WESTCLOCKERROR/1000. ;
01515
01516
01517 Xprime[0] = r * TMath::Cos(phi) ;
01518 Xprime[1] = r * TMath::Sin(phi) ;
01519 Xprime[2] = x[2] ;
01520
01521 }
01522
01523
01524
01525
01526
01528
01531 void StMagUtilities::UndoMembraneDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01532 {
01533
01534 cout << "StMagUtilities::UndoMembrane This routine was made obosolete on 10/1/2009. Do not use it." << endl ;
01535 exit(0) ;
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565 }
01566
01567
01568
01569
01570
01572
01575 void StMagUtilities::UndoEndcapDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01576 {
01577
01578 cout << "StMagUtilities::UndoEndcap This routine was made obosolete on 10/1/2009. Do not use it." << endl ;
01579 exit(0) ;
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609 }
01610
01611
01612
01613
01614
01616
01624 void StMagUtilities::UndoIFCShiftDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01625 {
01626
01627 Float_t Er_integral, Ephi_integral ;
01628 Double_t r, phi, z ;
01629
01630 static Int_t DoOnce = 0 ;
01631 const Int_t ORDER = 1 ;
01632
01633 if ( DoOnce == 0 )
01634 {
01635 cout << "StMagUtilities::IFCShift Please wait for the tables to fill ... ~5 seconds" << endl ;
01636 Int_t Nterms = 100 ;
01637 for ( Int_t i = 0 ; i < EMap_nZ ; ++i )
01638 {
01639 z = TMath::Abs( eZList[i] ) ;
01640 for ( Int_t j = 0 ; j < EMap_nR ; ++j )
01641 {
01642 r = eRList[j] ;
01643 shiftEr[i][j] = 0.0 ;
01644 if (r < IFCRadius) continue;
01645 if (r > OFCRadius) continue;
01646 if (z > TPC_Z0) continue;
01647 Double_t IntegralOverZ = 0.0 ;
01648 for ( Int_t n = 1 ; n < Nterms ; ++n )
01649 {
01650 Double_t k = (2*n-1) * TMath::Pi() / TPC_Z0 ;
01651 Double_t Cn = -4.0 * IFCShift / ( k * TPC_Z0 ) ;
01652 Double_t Numerator =
01653 TMath::BesselK0( k*OFCRadius ) * TMath::BesselI1( k*r ) +
01654 TMath::BesselK1( k*r ) * TMath::BesselI0( k*OFCRadius ) ;
01655 Double_t Denominator =
01656 TMath::BesselK0( k*OFCRadius ) * TMath::BesselI0( k*IFCRadius ) -
01657 TMath::BesselK0( k*IFCRadius ) * TMath::BesselI0( k*OFCRadius ) ;
01658 Double_t zterm = 1 + TMath::Cos( k*z ) ;
01659 Double_t qwe = Numerator / Denominator ;
01660 IntegralOverZ += Cn * zterm * qwe ;
01661 if ( n>10 && fabs(IntegralOverZ)*1.e-10 > fabs(qwe) ) break;
01662 }
01663 if ( eZList[i] < 0 ) IntegralOverZ = -1 * IntegralOverZ ;
01664 shiftEr[i][j] = IntegralOverZ ; }
01665 }
01666 DoOnce = 1 ;
01667 }
01668
01669 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
01670 phi = TMath::ATan2(x[1],x[0]) ;
01671 if ( phi < 0 ) phi += TMath::TwoPi() ;
01672 z = LimitZ( Sector, x ) ;
01673
01674 Interpolate2DEdistortion( ORDER, r, z, shiftEr, Er_integral ) ;
01675 Ephi_integral = 0.0 ;
01676
01677
01678 if ( r > 0.0 )
01679 {
01680 phi = phi - ( Const_0*Ephi_integral - Const_1*Er_integral ) / r ;
01681 r = r - ( Const_0*Er_integral + Const_1*Ephi_integral ) ;
01682 }
01683
01684 Xprime[0] = r * TMath::Cos(phi) ;
01685 Xprime[1] = r * TMath::Sin(phi) ;
01686 Xprime[2] = x[2] ;
01687
01688 }
01689
01690
01691
01692
01693
01695
01701 void StMagUtilities::UndoSpaceChargeDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01702 {
01703
01704 Float_t Er_integral, Ephi_integral ;
01705 Double_t r, phi, z ;
01706
01707 static Int_t DoOnce = 0 ;
01708 const Int_t ORDER = 1 ;
01709
01710 if ( DoOnce == 0 )
01711 {
01712 Int_t Nterms = 100 ;
01713 for ( Int_t i = 0 ; i < EMap_nZ ; ++i )
01714 {
01715 z = TMath::Abs( eZList[i] ) ;
01716 for ( Int_t j = 0 ; j < EMap_nR ; ++j )
01717 {
01718 r = eRList[j] ;
01719 spaceEr[i][j] = 0.0 ;
01720 if (r < IFCRadius) continue;
01721 if (r > OFCRadius) continue;
01722 if (z > TPC_Z0) continue;
01723 Double_t IntegralOverZ = 0.0 ;
01724 for ( Int_t n = 1 ; n < Nterms ; ++n )
01725 {
01726 Double_t k = n * TMath::Pi() / TPC_Z0 ;
01727 Double_t zterm = TMath::Power(-1,(n+1)) * ( 1.0 - TMath::Cos( k * ( TPC_Z0 - z ) ) ) ;
01728
01729
01730 Double_t Cn = -4.0 / ( k*k*k * TPC_Z0 * StarMagE ) ;
01731 Double_t Numerator =
01732 TMath::BesselI1( k*r ) * TMath::BesselK0( k*OFCRadius ) -
01733 TMath::BesselI1( k*r ) * TMath::BesselK0( k*IFCRadius ) +
01734 TMath::BesselK1( k*r ) * TMath::BesselI0( k*OFCRadius ) -
01735 TMath::BesselK1( k*r ) * TMath::BesselI0( k*IFCRadius ) ;
01736 Double_t Denominator =
01737 TMath::BesselK0( k*OFCRadius ) * TMath::BesselI0( k*IFCRadius ) -
01738 TMath::BesselK0( k*IFCRadius ) * TMath::BesselI0( k*OFCRadius ) ;
01739 Double_t qwe = Numerator / Denominator ;
01740 IntegralOverZ += Cn * zterm * qwe ;
01741 if ( n>10 && fabs(IntegralOverZ)*1.e-10 > fabs(qwe) ) break;
01742 }
01743 spaceEr[i][j] = IntegralOverZ ;
01744 }
01745 }
01746 DoOnce = 1 ;
01747 }
01748
01749 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
01750 phi = TMath::ATan2(x[1],x[0]) ;
01751 if ( phi < 0 ) phi += TMath::TwoPi() ;
01752 z = LimitZ( Sector, x ) ;
01753
01754 Interpolate2DEdistortion( ORDER, r, z, spaceEr, Er_integral ) ;
01755 Ephi_integral = 0.0 ;
01756
01757
01758
01759 if (fSpaceCharge) GetSpaceCharge();
01760
01761
01762 if ( r > 0.0 )
01763 {
01764 phi = phi - SpaceCharge * ( Const_0*Ephi_integral - Const_1*Er_integral ) / r ;
01765 r = r - SpaceCharge * ( Const_0*Er_integral + Const_1*Ephi_integral ) ;
01766 }
01767
01768 Xprime[0] = r * TMath::Cos(phi) ;
01769 Xprime[1] = r * TMath::Sin(phi) ;
01770 Xprime[2] = x[2] ;
01771
01772 }
01773
01774
01775
01776
01777
01779
01792 void StMagUtilities::UndoSpaceChargeR2Distortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01793 {
01794
01795 const Int_t ORDER = 1 ;
01796 const Int_t ROWS = 257 ;
01797 const Int_t COLUMNS = 129 ;
01798 const Int_t ITERATIONS = 100 ;
01799 const Double_t GRIDSIZER = (OFCRadius-IFCRadius) / (ROWS-1) ;
01800 const Double_t GRIDSIZEZ = TPC_Z0 / (COLUMNS-1) ;
01801
01802 Float_t Er_integral, Ephi_integral ;
01803 Double_t r, phi, z ;
01804
01805 static Int_t DoOnce = 0 ;
01806
01807 if ( DoOnce == 0 )
01808 {
01809 cout << "StMagUtilities::UndoSpace Please wait for the tables to fill ... ~5 seconds" << endl ;
01810 TMatrix ArrayV(ROWS,COLUMNS), Charge(ROWS,COLUMNS) ;
01811 TMatrix ArrayE(ROWS,COLUMNS), EroverEz(ROWS,COLUMNS) ;
01812 Float_t Rlist[ROWS], Zedlist[COLUMNS] ;
01813
01814
01815 for ( Int_t j = 0 ; j < COLUMNS ; j++ )
01816 {
01817 Double_t zed = j*GRIDSIZEZ ;
01818 Zedlist[j] = zed ;
01819 for ( Int_t i = 0 ; i < ROWS ; i++ )
01820 {
01821 Double_t Radius = IFCRadius + i*GRIDSIZER ;
01822 ArrayV(i,j) = 0 ;
01823 Charge(i,j) = 0 ;
01824 Rlist[i] = Radius ;
01825 }
01826 }
01827
01828 for ( Int_t j = 1 ; j < COLUMNS-1 ; j++ )
01829 {
01830 Double_t zed = j*GRIDSIZEZ ;
01831 for ( Int_t i = 1 ; i < ROWS-1 ; i++ )
01832 {
01833 Double_t Radius = IFCRadius + i*GRIDSIZER ;
01834 Double_t zterm = (TPC_Z0-zed) * (OFCRadius*OFCRadius - IFCRadius*IFCRadius) / TPC_Z0 ;
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846 Charge(i,j) = zterm * ( 3191/(Radius*Radius) + 122.5/Radius - 0.395 ) / 15823 ;
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859 }
01860 }
01861
01862 PoissonRelaxation( ArrayV, Charge, EroverEz, ITERATIONS ) ;
01863
01864
01865 Int_t ilow=0, jlow=0 ;
01866 Float_t save_Er[2] ;
01867 for ( Int_t i = 0 ; i < EMap_nZ ; ++i )
01868 {
01869 z = TMath::Abs( eZList[i] ) ;
01870 for ( Int_t j = 0 ; j < EMap_nR ; ++j )
01871 {
01872 r = eRList[j] ;
01873 Search( ROWS, Rlist, r, ilow ) ;
01874 Search( COLUMNS, Zedlist, z, jlow ) ;
01875 if ( ilow < 0 ) ilow = 0 ;
01876 if ( jlow < 0 ) jlow = 0 ;
01877 if ( ilow + 1 >= ROWS - 1 ) ilow = ROWS - 2 ;
01878 if ( jlow + 1 >= COLUMNS - 1 ) jlow = COLUMNS - 2 ;
01879 save_Er[0] = EroverEz(ilow,jlow) + (EroverEz(ilow,jlow+1)-EroverEz(ilow,jlow))*(z-Zedlist[jlow])/GRIDSIZEZ ;
01880 save_Er[1] = EroverEz(ilow+1,jlow) + (EroverEz(ilow+1,jlow+1)-EroverEz(ilow+1,jlow))*(z-Zedlist[jlow])/GRIDSIZEZ ;
01881 spaceR2Er[i][j] = save_Er[0] + (save_Er[1]-save_Er[0])*(r-Rlist[ilow])/GRIDSIZER ;
01882 }
01883 }
01884
01885 DoOnce = 1 ;
01886
01887 }
01888
01889 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
01890 phi = TMath::ATan2(x[1],x[0]) ;
01891 if ( phi < 0 ) phi += TMath::TwoPi() ;
01892 z = LimitZ( Sector, x ) ;
01893
01894 Interpolate2DEdistortion( ORDER, r, z, spaceR2Er, Er_integral ) ;
01895 Ephi_integral = 0.0 ;
01896
01897
01898
01899 if (fSpaceChargeR2) GetSpaceChargeR2();
01900
01901
01902 if ( r > 0.0 )
01903 {
01904 if ( z < 0.0 )
01905 {
01906 phi = phi - SpaceChargeR2 * SpaceChargeEWRatio * ( Const_0*Ephi_integral - Const_1*Er_integral ) / r ;
01907 r = r - SpaceChargeR2 * SpaceChargeEWRatio * ( Const_0*Er_integral + Const_1*Ephi_integral ) ;
01908 }
01909 else
01910 {
01911 phi = phi - SpaceChargeR2 * ( Const_0*Ephi_integral - Const_1*Er_integral ) / r ;
01912 r = r - SpaceChargeR2 * ( Const_0*Er_integral + Const_1*Ephi_integral ) ;
01913 }
01914 }
01915
01916 Xprime[0] = r * TMath::Cos(phi) ;
01917 Xprime[1] = r * TMath::Sin(phi) ;
01918 Xprime[2] = x[2] ;
01919
01920 }
01921
01922
01923
01924
01925
01927
01949 void StMagUtilities::UndoShortedRingDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
01950 {
01951
01952 const Int_t ORDER = 1 ;
01953 const Float_t R0 = 2.130 ;
01954 const Float_t R182 = 0.310 ;
01955 const Float_t RStep = 2.000 ;
01956 const Float_t Pitch = 1.150 ;
01957 const Float_t Z01 = 1.225 ;
01958
01959 static Bool_t DoOnce = true ;
01960 static Int_t NumberOfEastInnerShorts = 0, NumberOfEastOuterShorts = 0 , NumberOfWestInnerShorts = 0, NumberOfWestOuterShorts = 0 ;
01961
01962 Float_t Er_integral, Ephi_integral ;
01963 Double_t r, phi, z ;
01964
01965 if (fTpcVolts) DoOnce = UpdateShortedRing() ;
01966
01967 if ( DoOnce )
01968 {
01969
01970 cout << "StMagUtilities::UndoShort Please wait for the tables to fill ... ~5 seconds" << endl ;
01971
01972
01973
01974
01975 Float_t EastInnerMissingSum = 0, EastOuterMissingSum = 0, WestInnerMissingSum = 0, WestOuterMissingSum = 0 ;
01976 Float_t EastInnerExtraSum = 0, EastOuterExtraSum = 0, WestInnerExtraSum = 0, WestOuterExtraSum = 0 ;
01977 Float_t EastInnerMissingOhms[10], EastOuterMissingOhms[10], WestInnerMissingOhms[10], WestOuterMissingOhms[10] ;
01978 Float_t EastInnerShortZ[10], EastOuterShortZ[10], WestInnerShortZ[10], WestOuterShortZ[10] ;
01979
01980 NumberOfEastInnerShorts = 0; NumberOfEastOuterShorts = 0 ; NumberOfWestInnerShorts = 0; NumberOfWestOuterShorts = 0 ;
01981
01982 for ( Int_t i = 0 ; i < ShortTableRows ; i++ )
01983 {
01984 if ( ( Side[i] + Cage[i] + Ring[i] + TMath::Abs(MissingResistance[i]) + TMath::Abs(Resistor[i]) ) == 0.0 ) continue ;
01985 if ( Side[i] == 0 && Cage[i] == 0 )
01986 { NumberOfEastInnerShorts++ ; EastInnerMissingSum += MissingResistance[i] ; EastInnerExtraSum += Resistor[i] ;
01987 EastInnerMissingOhms[NumberOfEastInnerShorts-1] = MissingResistance[i] ;
01988 EastInnerShortZ[NumberOfEastInnerShorts-1] = TPC_Z0 - ( Z01 + (Ring[i]-1)*Pitch) ; }
01989 if ( Side[i] == 0 && Cage[i] == 1 )
01990 { NumberOfEastOuterShorts++ ; EastOuterMissingSum += MissingResistance[i] ; EastOuterExtraSum += Resistor[i] ;
01991 EastOuterMissingOhms[NumberOfEastOuterShorts-1] = MissingResistance[i] ;
01992 EastOuterShortZ[NumberOfEastOuterShorts-1] = TPC_Z0 - ( Z01 + (Ring[i]-1)*Pitch) ; }
01993 if ( Side[i] == 1 && Cage[i] == 0 )
01994 { NumberOfWestInnerShorts++ ; WestInnerMissingSum += MissingResistance[i] ; WestInnerExtraSum += Resistor[i] ;
01995 WestInnerMissingOhms[NumberOfWestInnerShorts-1] = MissingResistance[i] ;
01996 WestInnerShortZ[NumberOfWestInnerShorts-1] = TPC_Z0 - ( Z01 + (Ring[i]-1)*Pitch) ; }
01997 if ( Side[i] == 1 && Cage[i] == 1 )
01998 { NumberOfWestOuterShorts++ ; WestOuterMissingSum += MissingResistance[i] ; WestOuterExtraSum += Resistor[i] ;
01999 WestOuterMissingOhms[NumberOfWestOuterShorts-1] = MissingResistance[i] ;
02000 WestOuterShortZ[NumberOfWestOuterShorts-1] = TPC_Z0 - ( Z01 + (Ring[i]-1)*Pitch) ; }
02001 }
02002
02003
02004 if ( (NumberOfEastInnerShorts + NumberOfEastOuterShorts + NumberOfWestInnerShorts + NumberOfWestOuterShorts) == 0 )
02005 { Xprime[0] = x[0] ; Xprime[1] = x[1] ; Xprime[2] = x[2] ; return ; }
02006
02007 Float_t Rtot = R0 + 181*RStep + R182 ;
02008 Float_t Rfrac = RStep*TPC_Z0/(Rtot*Pitch) ;
02009 Float_t EastInnerRtot = Rtot + EastInnerExtraSum - EastInnerMissingSum ;
02010 Float_t EastOuterRtot = Rtot + EastOuterExtraSum - EastOuterMissingSum ;
02011 Float_t WestInnerRtot = Rtot + WestInnerExtraSum - WestInnerMissingSum ;
02012 Float_t WestOuterRtot = Rtot + WestOuterExtraSum - WestOuterMissingSum ;
02013
02014
02015
02016 Int_t Nterms = 100 ;
02017 for ( Int_t i = 0 ; i < EMap_nZ ; ++i )
02018 {
02019 z = eZList[i] ;
02020 for ( Int_t j = 0 ; j < EMap_nR ; ++j )
02021 {
02022 r = eRList[j] ;
02023 shortEr[i][j] = 0.0 ;
02024 if (r < IFCRadius) continue;
02025 if (r > OFCRadius) continue;
02026 if (TMath::Abs(z) > TPC_Z0) continue;
02027 Double_t IntegralOverZ = 0.0 ;
02028 for ( Int_t n = 1 ; n < Nterms ; ++n )
02029 {
02030 Double_t k = n * TMath::Pi() / TPC_Z0 ;
02031 Double_t Ein = 0 ;
02032 Double_t Eout = 0 ;
02033 Double_t sum = 0 ;
02034 if ( z < 0 )
02035 {
02036 sum = 0.0 ;
02037 for ( Int_t m = 0 ; m < NumberOfEastInnerShorts ; m++ )
02038 sum += ( 1 - Rfrac - TMath::Cos(k*EastInnerShortZ[m]) ) * EastInnerMissingOhms[m] ;
02039 Ein = 2 * ( Rfrac*EastInnerExtraSum + sum ) / (k*EastInnerRtot*TPC_Z0) ;
02040 sum = 0.0 ;
02041 for ( Int_t m = 0 ; m < NumberOfEastOuterShorts ; m++ )
02042 sum += ( 1 - Rfrac - TMath::Cos(k*EastOuterShortZ[m]) ) * EastOuterMissingOhms[m] ;
02043 Eout = 2 * ( Rfrac*EastOuterExtraSum + sum ) / (k*EastOuterRtot*TPC_Z0) ;
02044 }
02045 if ( z == 0 ) continue ;
02046 if ( z > 0 )
02047 {
02048 sum = 0.0 ;
02049 for ( Int_t m = 0 ; m < NumberOfWestInnerShorts ; m++ )
02050 sum += ( 1 - Rfrac - TMath::Cos(k*WestInnerShortZ[m]) ) * WestInnerMissingOhms[m] ;
02051 Ein = 2 * ( Rfrac*WestInnerExtraSum + sum ) / (k*WestInnerRtot*TPC_Z0) ;
02052 sum = 0.0 ;
02053 for ( Int_t m = 0 ; m < NumberOfWestOuterShorts ; m++ )
02054 sum += ( 1 - Rfrac - TMath::Cos(k*WestOuterShortZ[m]) ) * WestOuterMissingOhms[m] ;
02055 Eout = 2 * ( Rfrac*WestOuterExtraSum + sum ) / (k*WestOuterRtot*TPC_Z0) ;
02056 }
02057
02058
02059
02060
02061
02062
02063 Double_t An = Ein * TMath::BesselK0( k*OFCRadius ) - Eout * TMath::BesselK0( k*IFCRadius ) ;
02064 Double_t Bn = Eout * TMath::BesselI0( k*IFCRadius ) - Ein * TMath::BesselI0( k*OFCRadius ) ;
02065 Double_t Numerator =
02066 An * TMath::BesselI1( k*r ) - Bn * TMath::BesselK1( k*r ) ;
02067 Double_t Denominator =
02068 TMath::BesselK0( k*OFCRadius ) * TMath::BesselI0( k*IFCRadius ) -
02069 TMath::BesselK0( k*IFCRadius ) * TMath::BesselI0( k*OFCRadius ) ;
02070 Double_t zterm = TMath::Cos( k*(TPC_Z0-TMath::Abs(z)) ) - 1 ;
02071 Double_t qwe = Numerator / Denominator ;
02072 IntegralOverZ += TPC_Z0 * zterm * qwe ;
02073 if ( n>10 && fabs(IntegralOverZ)*1.e-10 > fabs(qwe) ) break;
02074 }
02075 shortEr[i][j] = IntegralOverZ ;
02076 }
02077 }
02078 DoOnce = false ;
02079 }
02080
02081 if ( (NumberOfEastInnerShorts + NumberOfEastOuterShorts + NumberOfWestInnerShorts + NumberOfWestOuterShorts) == 0 )
02082 { Xprime[0] = x[0] ; Xprime[1] = x[1] ; Xprime[2] = x[2] ; return ; }
02083
02084 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
02085 phi = TMath::ATan2(x[1],x[0]) ;
02086 if ( phi < 0 ) phi += TMath::TwoPi() ;
02087 z = LimitZ( Sector, x ) ;
02088
02089 Interpolate2DEdistortion( ORDER, r, z, shortEr, Er_integral ) ;
02090 Ephi_integral = 0.0 ;
02091
02092
02093 if ( r > 0.0 )
02094 {
02095 phi = phi - ( Const_0*Ephi_integral - Const_1*Er_integral ) / r ;
02096 r = r - ( Const_0*Er_integral + Const_1*Ephi_integral ) ;
02097 }
02098
02099 Xprime[0] = r * TMath::Cos(phi) ;
02100 Xprime[1] = r * TMath::Sin(phi) ;
02101 Xprime[2] = x[2] ;
02102
02103 }
02104
02105
02106
02107
02108
02110
02119 void StMagUtilities::UndoGGVoltErrorDistortion( const Float_t x[], Float_t Xprime[], Int_t Sector )
02120 {
02121
02122 const Int_t ORDER = 1 ;
02123
02124 static Bool_t DoOnce = true ;
02125
02126 Float_t Er_integral, Ephi_integral ;
02127 Double_t r, phi, z ;
02128
02129
02130
02131 if ( DoOnce )
02132 {
02133
02134 cout << "StMagUtilities::UndoGG VE Please wait for the tables to fill ... ~5 seconds" << endl ;
02135
02136 Int_t Nterms = 100 ;
02137 for ( Int_t i = 0 ; i < EMap_nZ ; ++i )
02138 {
02139 z = eZList[i] ;
02140 for ( Int_t j = 0 ; j < EMap_nR ; ++j )
02141 {
02142 r = eRList[j] ;
02143 GGVoltErrorEr[i][j] = 0.0 ;
02144 if (r < IFCRadius) continue;
02145 if (r > OFCRadius) continue;
02146 if (TMath::Abs(z) > TPC_Z0) continue;
02147 Double_t IntegralOverZ = 0.0 ;
02148 for ( Int_t n = 1 ; n < Nterms ; ++n )
02149 {
02150 Double_t k = n * TMath::Pi() / TPC_Z0 ;
02151 Double_t Ein = 0 ;
02152 Double_t Eout = 0 ;
02153 if ( z < 0 )
02154 {
02155 Ein = -2.0 * deltaVGGEast / ( k * (CathodeV - GG) ) ;
02156 Eout = -2.0 * deltaVGGEast / ( k * (CathodeV - GG) ) ;
02157
02158 }
02159 if ( z == 0 ) continue ;
02160 if ( z > 0 )
02161 {
02162 Ein = -2.0 * deltaVGGWest / ( k * (CathodeV - GG) ) ;
02163 Eout = -2.0 * deltaVGGWest / ( k * (CathodeV - GG) ) ;
02164 }
02165
02166 Double_t An = Ein * TMath::BesselK0( k*OFCRadius ) - Eout * TMath::BesselK0( k*IFCRadius ) ;
02167 Double_t Bn = Eout * TMath::BesselI0( k*IFCRadius ) - Ein * TMath::BesselI0( k*OFCRadius ) ;
02168 Double_t Numerator =
02169 An * TMath::BesselI1( k*r ) - Bn * TMath::BesselK1( k*r ) ;
02170 Double_t Denominator =
02171 TMath::BesselK0( k*OFCRadius ) * TMath::BesselI0( k*IFCRadius ) -
02172 TMath::BesselK0( k*IFCRadius ) * TMath::BesselI0( k*OFCRadius ) ;
02173 Double_t zterm = TMath::Cos( k*(TPC_Z0-TMath::Abs(z)) ) - 1 ;
02174 IntegralOverZ += zterm * Numerator / Denominator ;
02175 if ( n>10 && fabs(IntegralOverZ)*1.e-10 > fabs(Numerator/Denominator) ) break;
02176 }
02177 GGVoltErrorEr[i][j] = IntegralOverZ ;
02178 }
02179 }
02180 DoOnce = false ;
02181 }
02182
02183 if ( deltaVGGEast == 0.0 && deltaVGGWest == 0 )
02184 { Xprime[0] = x[0] ; Xprime[1] = x[1] ; Xprime[2] = x[2] ; return ; }
02185
02186 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
02187 phi = TMath::ATan2(x[1],x[0]) ;
02188 if ( phi < 0 ) phi += TMath::TwoPi() ;
02189 z = LimitZ( Sector, x ) ;
02190
02191 Interpolate2DEdistortion( ORDER, r, z, GGVoltErrorEr, Er_integral ) ;
02192 Ephi_integral = 0.0 ;
02193
02194
02195 if ( r > 0.0 )
02196 {
02197 phi = phi - ( Const_0*Ephi_integral - Const_1*Er_integral ) / r ;
02198 r = r - ( Const_0*Er_integral + Const_1*Ephi_integral ) ;
02199 }
02200
02201 Xprime[0] = r * TMath::Cos(phi) ;
02202 Xprime[1] = r * TMath::Sin(phi) ;
02203 Xprime[2] = x[2] ;
02204
02205 }
02206
02207
02208
02209
02210
02212 void StMagUtilities::ReadField( )
02213 {
02214
02215 FILE *magfile, *b3Dfile ;
02216 TString comment, filename, filename3D ;
02217 TString MapLocation ;
02218 TString BaseLocation = "$STAR/StarDb/StMagF/" ;
02219
02220 if ( gMap == kMapped )
02221 {
02222 if ( TMath::Abs(gFactor) > 0.8 )
02223 {
02224 if ( gFactor > 0 )
02225 {
02226 filename = "bfield_full_positive_2D.dat" ;
02227 filename3D = "bfield_full_positive_3D.dat" ;
02228 comment = "Measured Full Field" ;
02229 gRescale = 1 ;
02230 }
02231 else
02232 {
02233 filename = "bfield_full_negative_2D.dat" ;
02234 filename3D = "bfield_full_negative_3D.dat" ;
02235 comment = "Measured Full Field Reversed" ;
02236 gRescale = -1 ;
02237 }
02238 }
02239 else
02240 {
02241 filename = "bfield_half_positive_2D.dat" ;
02242 filename3D = "bfield_half_positive_3D.dat" ;
02243 comment = "Measured Half Field" ;
02244 gRescale = 2 ;
02245 }
02246 }
02247 else if ( gMap == kConstant )
02248 {
02249 filename = "const_full_positive_2D.dat" ;
02250 comment = "Constant Full Field" ;
02251 gRescale = 1 ;
02252 }
02253 else
02254 {
02255 fprintf(stderr,"StMagUtilities::ReadField No map available - you must choose a mapped field or a constant field\n");
02256 exit(1) ;
02257 }
02258
02259 printf("StMagUtilities::ReadField Reading Magnetic Field %s, Scale factor = %f \n",comment.Data(),gFactor);
02260 printf("StMagUtilities::ReadField Filename is %s, Adjusted Scale factor = %f \n",filename.Data(),gFactor*gRescale);
02261 printf("StMagUtilities::ReadField Version ") ;
02262
02263 if ( mDistortionMode & kBMap ) printf ("3D Mag Field Distortions") ;
02264 if ( mDistortionMode & kFast2DBMap ) printf ("2D Mag Field Distortions") ;
02265 if ( mDistortionMode & kPadrow13 ) printf (" + Padrow 13") ;
02266 if ( mDistortionMode & kTwist ) printf (" + Twist") ;
02267 if ( mDistortionMode & kClock ) printf (" + Clock") ;
02268 if ( mDistortionMode & kIFCShift ) printf (" + IFCShift") ;
02269 if ( mDistortionMode & kSpaceCharge ) printf (" + SpaceCharge") ;
02270 if ( mDistortionMode & kSpaceChargeR2 ) printf (" + SpaceChargeR2") ;
02271 if ( mDistortionMode & kMembrane ) printf (" + Central Membrane") ;
02272 if ( mDistortionMode & kEndcap ) printf (" + Endcap") ;
02273 if ( mDistortionMode & kShortedRing ) printf (" + ShortedRing") ;
02274 if ( mDistortionMode & kGridLeak ) printf (" + GridLeak") ;
02275 if ( mDistortionMode & k3DGridLeak ) printf (" + 3DGridLeak") ;
02276 if ( mDistortionMode & kGGVoltError ) printf (" + GGVoltError") ;
02277 if ( mDistortionMode & kSectorAlign ) printf (" + Sector Misalignment") ;
02278
02279 printf("\n");
02280
02281 MapLocation = BaseLocation + filename ;
02282 gSystem->ExpandPathName(MapLocation) ;
02283 magfile = fopen(MapLocation.Data(),"r") ;
02284 printf("StMagUtilities::ReadField Reading 2D Magnetic Field file: %s \n",filename.Data());
02285
02286 if (magfile)
02287
02288 {
02289 Char_t cname[128] ;
02290 fgets ( cname, sizeof(cname) , magfile ) ;
02291 fgets ( cname, sizeof(cname) , magfile ) ;
02292 fgets ( cname, sizeof(cname) , magfile ) ;
02293 fgets ( cname, sizeof(cname) , magfile ) ;
02294 fgets ( cname, sizeof(cname) , magfile ) ;
02295
02296 for ( Int_t j=0 ; j < BMap_nZ ; j++ )
02297 {
02298 for ( Int_t k=0 ; k < BMap_nR ; k++ )
02299 {
02300 fgets ( cname, sizeof(cname) , magfile ) ;
02301 sscanf ( cname, " %f %f %f %f ", &Radius[k], &ZList[j], &Br[j][k], &Bz[j][k] ) ;
02302 }
02303 }
02304 }
02305
02306 else
02307
02308 {
02309 fprintf(stderr,"StMagUtilities::ReadField File %s not found !\n",MapLocation.Data());
02310 exit(1);
02311 }
02312
02313 fclose(magfile) ;
02314
02315 MapLocation = BaseLocation + filename3D ;
02316 gSystem->ExpandPathName(MapLocation) ;
02317 b3Dfile = fopen(MapLocation.Data(),"r") ;
02318 printf("StMagUtilities::ReadField Reading 3D Magnetic Field file: %s \n",filename3D.Data());
02319
02320 if (b3Dfile)
02321
02322 {
02323 Char_t cname[128] ;
02324 fgets ( cname, sizeof(cname) , b3Dfile ) ;
02325 fgets ( cname, sizeof(cname) , b3Dfile ) ;
02326 fgets ( cname, sizeof(cname) , b3Dfile ) ;
02327 fgets ( cname, sizeof(cname) , b3Dfile ) ;
02328 fgets ( cname, sizeof(cname) , b3Dfile ) ;
02329 fgets ( cname, sizeof(cname) , b3Dfile ) ;
02330
02331 for ( Int_t i=0 ; i < BMap_nPhi ; i++ )
02332 {
02333 for ( Int_t j=0 ; j < BMap_nZ ; j++ )
02334 {
02335 for ( Int_t k=0 ; k < BMap_nR ; k++ )
02336 {
02337 fgets ( cname, sizeof(cname) , b3Dfile ) ;
02338 sscanf ( cname, " %f %f %f %f %f %f ",
02339 &R3D[k], &Z3D[j], &Phi3D[i], &Br3D[i][j][k], &Bz3D[i][j][k], &Bphi3D[i][j][k] ) ;
02340 Phi3D[i] *= TMath::Pi() / 180. ;
02341 }
02342 }
02343 }
02344 }
02345
02346 else if ( gMap == kConstant )
02347
02348 {
02349 for ( Int_t i=0 ; i < BMap_nPhi ; i++ )
02350 {
02351 for ( Int_t j=0 ; j < BMap_nZ ; j++ )
02352 {
02353 for ( Int_t k=0 ; k < BMap_nR ; k++ )
02354 {
02355 Br3D[i][j][k] = Br[j][k] ;
02356 Bz3D[i][j][k] = Bz[j][k] ;
02357 Bphi3D[i][j][k] = 0 ;
02358 }
02359 }
02360 }
02361 }
02362
02363 else
02364
02365 {
02366 fprintf(stderr,"StMagUtilities::ReadField File %s not found !\n",MapLocation.Data());
02367 exit(1);
02368 }
02369
02370 fclose(b3Dfile) ;
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481 return ;
02482
02483 }
02484
02485
02486
02487
02489 void StMagUtilities::Interpolate2DBfield( const Float_t r, const Float_t z, Float_t &Br_value, Float_t &Bz_value )
02490 {
02491
02492 Float_t fscale ;
02493
02494 fscale = 0.001*gFactor*gRescale ;
02495 if ( TMath::Abs(fscale) < 4e-7 ) fscale = 4e-7 ;
02496
02497
02498
02499 const Int_t ORDER = 1 ;
02500 static Int_t jlow=0, klow=0 ;
02501 Float_t save_Br[ORDER+1] ;
02502 Float_t save_Bz[ORDER+1] ;
02503
02504 Search ( BMap_nZ, ZList, z, jlow ) ;
02505 Search ( BMap_nR, Radius, r, klow ) ;
02506 if ( jlow < 0 ) jlow = 0 ;
02507 if ( klow < 0 ) klow = 0 ;
02508 if ( jlow + ORDER >= BMap_nZ - 1 ) jlow = BMap_nZ - 1 - ORDER ;
02509 if ( klow + ORDER >= BMap_nR - 1 ) klow = BMap_nR - 1 - ORDER ;
02510
02511 for ( Int_t j = jlow ; j < jlow + ORDER + 1 ; j++ )
02512 {
02513 save_Br[j-jlow] = Interpolate( &Radius[klow], &Br[j][klow], ORDER, r ) ;
02514 save_Bz[j-jlow] = Interpolate( &Radius[klow], &Bz[j][klow], ORDER, r ) ;
02515 }
02516 Br_value = fscale * Interpolate( &ZList[jlow], save_Br, ORDER, z ) ;
02517 Bz_value = fscale * Interpolate( &ZList[jlow], save_Bz, ORDER, z ) ;
02518
02519 }
02520
02522 void StMagUtilities::Interpolate3DBfield( const Float_t r, const Float_t z, const Float_t phi,
02523 Float_t &Br_value, Float_t &Bz_value, Float_t &Bphi_value )
02524 {
02525
02526 Float_t fscale ;
02527
02528 fscale = 0.001*gFactor*gRescale ;
02529 if ( TMath::Abs(fscale) < 4e-7 ) fscale = 4e-7 ;
02530
02531 const Int_t ORDER = 1 ;
02532 const Int_t PHIORDER = 1 ;
02533 static Int_t ilow=0, jlow=0, klow=0 ;
02534 Float_t save_Br[ORDER+1], saved_Br[ORDER+1] ;
02535 Float_t save_Bz[ORDER+1], saved_Bz[ORDER+1] ;
02536 Float_t save_Bphi[ORDER+1], saved_Bphi[ORDER+1] ;
02537
02538 Search( BMap_nPhi, Phi3D, phi, ilow ) ;
02539 Search( BMap_nZ, Z3D, z, jlow ) ;
02540 Search( BMap_nR, R3D, r, klow ) ;
02541 if ( ilow < 0 ) ilow = 0 ;
02542 if ( jlow < 0 ) jlow = 0 ;
02543 if ( klow < 0 ) klow = 0 ;
02544
02545 if ( ilow + ORDER >= BMap_nPhi - 1 ) ilow = BMap_nPhi - 1 - ORDER ;
02546 if ( jlow + ORDER >= BMap_nZ - 1 ) jlow = BMap_nZ - 1 - ORDER ;
02547 if ( klow + ORDER >= BMap_nR - 1 ) klow = BMap_nR - 1 - ORDER ;
02548
02549 for ( Int_t i = ilow ; i < ilow + ORDER + 1 ; i++ )
02550 {
02551 for ( Int_t j = jlow ; j < jlow + ORDER + 1 ; j++ )
02552 {
02553 save_Br[j-jlow] = Interpolate( &R3D[klow], &Br3D[i][j][klow], ORDER, r ) ;
02554 save_Bz[j-jlow] = Interpolate( &R3D[klow], &Bz3D[i][j][klow], ORDER, r ) ;
02555 save_Bphi[j-jlow] = Interpolate( &R3D[klow], &Bphi3D[i][j][klow], ORDER, r ) ;
02556 }
02557 saved_Br[i-ilow] = Interpolate( &Z3D[jlow], save_Br, ORDER, z ) ;
02558 saved_Bz[i-ilow] = Interpolate( &Z3D[jlow], save_Bz, ORDER, z ) ;
02559 saved_Bphi[i-ilow] = Interpolate( &Z3D[jlow], save_Bphi, ORDER, z ) ;
02560 }
02561 Br_value = fscale * Interpolate( &Phi3D[ilow], saved_Br, PHIORDER, phi ) ;
02562 Bz_value = fscale * Interpolate( &Phi3D[ilow], saved_Bz, PHIORDER, phi ) ;
02563 Bphi_value = fscale * Interpolate( &Phi3D[ilow], saved_Bphi, PHIORDER, phi ) ;
02564
02565 }
02566
02567
02568
02569
02571 Float_t StMagUtilities::Interpolate2DTable( const Int_t ORDER, const Float_t x, const Float_t y, const Int_t nx, const Int_t ny,
02572 const Float_t XV[], const Float_t YV[], const TMatrix &Array )
02573 {
02574
02575 static Int_t jlow = 0, klow = 0 ;
02576 Float_t save_Array[ORDER+1] ;
02577
02578 Search( nx, XV, x, jlow ) ;
02579 Search( ny, YV, y, klow ) ;
02580 if ( jlow < 0 ) jlow = 0 ;
02581 if ( klow < 0 ) klow = 0 ;
02582 if ( jlow + ORDER >= nx - 1 ) jlow = nx - 1 - ORDER ;
02583 if ( klow + ORDER >= ny - 1 ) klow = ny - 1 - ORDER ;
02584
02585 for ( Int_t j = jlow ; j < jlow + ORDER + 1 ; j++ )
02586 {
02587 Float_t *ajkl = &((TMatrix&)Array)(j,klow);
02588 save_Array[j-jlow] = Interpolate( &YV[klow], ajkl , ORDER, y ) ;
02589 }
02590
02591 return( Interpolate( &XV[jlow], save_Array, ORDER, x ) ) ;
02592
02593 }
02594
02596 void StMagUtilities::Interpolate2DEdistortion( const Int_t ORDER, const Float_t r, const Float_t z,
02597 const Float_t Er[EMap_nZ][EMap_nR], Float_t &Er_value )
02598 {
02599
02600 static Int_t jlow = 0, klow = 0 ;
02601 Float_t save_Er[ORDER+1] ;
02602
02603 Search( EMap_nZ, eZList, z, jlow ) ;
02604 Search( EMap_nR, eRList, r, klow ) ;
02605 if ( jlow < 0 ) jlow = 0 ;
02606 if ( klow < 0 ) klow = 0 ;
02607 if ( jlow + ORDER >= EMap_nZ - 1 ) jlow = EMap_nZ - 1 - ORDER ;
02608 if ( klow + ORDER >= EMap_nR - 1 ) klow = EMap_nR - 1 - ORDER ;
02609
02610 for ( Int_t j = jlow ; j < jlow + ORDER + 1 ; j++ )
02611 {
02612 save_Er[j-jlow] = Interpolate( &eRList[klow], &Er[j][klow], ORDER, r ) ;
02613 }
02614 Er_value = Interpolate( &eZList[jlow], save_Er, ORDER, z ) ;
02615
02616 }
02617
02619 void StMagUtilities::Interpolate3DEdistortion( const Int_t ORDER, const Float_t r, const Float_t phi, const Float_t z,
02620 const Float_t Er[EMap_nZ][EMap_nPhi][EMap_nR], const Float_t Ephi[EMap_nZ][EMap_nPhi][EMap_nR],
02621 Float_t &Er_value, Float_t &Ephi_value )
02622 {
02623
02624 static Int_t ilow = 0, jlow = 0, klow = 0 ;
02625 Float_t save_Er[ORDER+1], saved_Er[ORDER+1] ;
02626 Float_t save_Ephi[ORDER+1], saved_Ephi[ORDER+1] ;
02627
02628 Search( EMap_nZ, eZList, z, ilow ) ;
02629 Search( EMap_nPhi, ePhiList, phi, jlow ) ;
02630 Search( EMap_nR, eRList, r, klow ) ;
02631 if ( ilow < 0 ) ilow = 0 ;
02632 if ( jlow < 0 ) jlow = 0 ;
02633 if ( klow < 0 ) klow = 0 ;
02634
02635 if ( ilow + ORDER >= EMap_nZ - 1 ) ilow = EMap_nZ - 1 - ORDER ;
02636 if ( jlow + ORDER >= EMap_nPhi - 1 ) jlow = EMap_nPhi - 1 - ORDER ;
02637 if ( klow + ORDER >= EMap_nR - 1 ) klow = EMap_nR - 1 - ORDER ;
02638
02639 for ( Int_t i = ilow ; i < ilow + ORDER + 1 ; i++ )
02640 {
02641 for ( Int_t j = jlow ; j < jlow + ORDER + 1 ; j++ )
02642 {
02643 save_Er[j-jlow] = Interpolate( &eRList[klow], &Er[i][j][klow], ORDER, r ) ;
02644 save_Ephi[j-jlow] = Interpolate( &eRList[klow], &Ephi[i][j][klow], ORDER, r ) ;
02645 }
02646 saved_Er[i-ilow] = Interpolate( &ePhiList[jlow], save_Er, ORDER, phi ) ;
02647 saved_Ephi[i-ilow] = Interpolate( &ePhiList[jlow], save_Ephi, ORDER, phi ) ;
02648 }
02649 Er_value = Interpolate( &eZList[ilow], saved_Er, ORDER, z ) ;
02650 Ephi_value = Interpolate( &eZList[ilow], saved_Ephi, ORDER, z ) ;
02651
02652 }
02653
02654
02656 Float_t StMagUtilities::Interpolate3DTable ( const Int_t ORDER, const Float_t x, const Float_t y, const Float_t z,
02657 const Int_t nx, const Int_t ny, const Int_t nz,
02658 const Float_t XV[], const Float_t YV[], const Float_t ZV[],
02659 TMatrix **ArrayofArrays )
02660 {
02661
02662 static Int_t ilow = 0, jlow = 0, klow = 0 ;
02663 Float_t save_Array[ORDER+1], saved_Array[ORDER+1] ;
02664
02665 Search( nx, XV, x, ilow ) ;
02666 Search( ny, YV, y, jlow ) ;
02667 Search( nz, ZV, z, klow ) ;
02668
02669 if ( ilow < 0 ) ilow = 0 ;
02670 if ( jlow < 0 ) jlow = 0 ;
02671 if ( klow < 0 ) klow = 0 ;
02672
02673 if ( ilow + ORDER >= nx - 1 ) ilow = nx - 1 - ORDER ;
02674 if ( jlow + ORDER >= ny - 1 ) jlow = ny - 1 - ORDER ;
02675 if ( klow + ORDER >= nz - 1 ) klow = nz - 1 - ORDER ;
02676
02677 for ( Int_t k = klow ; k < klow + ORDER + 1 ; k++ )
02678 {
02679 TMatrix &Table = *ArrayofArrays[k] ;
02680 for ( Int_t i = ilow ; i < ilow + ORDER + 1 ; i++ )
02681 {
02682 save_Array[i-ilow] = Interpolate( &YV[jlow], &Table(i,jlow), ORDER, y ) ;
02683 }
02684 saved_Array[k-klow] = Interpolate( &XV[ilow], save_Array, ORDER, x ) ;
02685 }
02686 return( Interpolate( &ZV[klow], saved_Array, ORDER, z ) ) ;
02687
02688 }
02689
02690
02691
02692
02693
02695 Float_t StMagUtilities::Interpolate( const Float_t Xarray[], const Float_t Yarray[],
02696 const Int_t ORDER, const Float_t x )
02697 {
02698
02699 Float_t y ;
02700
02701 if ( ORDER == 2 )
02702
02703 {
02704 y = (x-Xarray[1]) * (x-Xarray[2]) * Yarray[0] / ( (Xarray[0]-Xarray[1]) * (Xarray[0]-Xarray[2]) ) ;
02705 y += (x-Xarray[2]) * (x-Xarray[0]) * Yarray[1] / ( (Xarray[1]-Xarray[2]) * (Xarray[1]-Xarray[0]) ) ;
02706 y += (x-Xarray[0]) * (x-Xarray[1]) * Yarray[2] / ( (Xarray[2]-Xarray[0]) * (Xarray[2]-Xarray[1]) ) ;
02707
02708 }
02709
02710 else
02711
02712 {
02713 y = Yarray[0] + ( Yarray[1]-Yarray[0] ) * ( x-Xarray[0] ) / ( Xarray[1] - Xarray[0] ) ;
02714 }
02715
02716 return (y) ;
02717
02718 }
02719
02720
02721
02722
02723
02725 void StMagUtilities::Search( const Int_t N, const Float_t Xarray[], const Float_t x, Int_t &low )
02726 {
02727
02728 Long_t middle, high ;
02729 Int_t ascend = 0, increment = 1 ;
02730
02731 if ( Xarray[N-1] >= Xarray[0] ) ascend = 1 ;
02732
02733 if ( low < 0 || low > N-1 ) { low = -1 ; high = N ; }
02734
02735 else
02736 {
02737 if ( (Int_t)( x >= Xarray[low] ) == ascend )
02738 {
02739 if ( low == N-1 ) return ;
02740 high = low + 1 ;
02741 while ( (Int_t)( x >= Xarray[high] ) == ascend )
02742 {
02743 low = high ;
02744 increment *= 2 ;
02745 high = low + increment ;
02746 if ( high > N-1 ) { high = N ; break ; }
02747 }
02748 }
02749 else
02750 {
02751 if ( low == 0 ) { low = -1 ; return ; }
02752 high = low - 1 ;
02753 while ( (Int_t)( x < Xarray[low] ) == ascend )
02754 {
02755 high = low ;
02756 increment *= 2 ;
02757 if ( increment >= high ) { low = -1 ; break ; }
02758 else low = high - increment ;
02759 }
02760 }
02761 }
02762
02763 while ( (high-low) != 1 )
02764 {
02765 middle = ( high + low ) / 2 ;
02766 if ( (Int_t)( x >= Xarray[middle] ) == ascend )
02767 low = middle ;
02768 else
02769 high = middle ;
02770 }
02771
02772 if ( x == Xarray[N-1] ) low = N-2 ;
02773 if ( x == Xarray[0] ) low = 0 ;
02774
02775 }
02776
02777
02778
02779
02780
02782
02798 void StMagUtilities::PoissonRelaxation( TMatrix &ArrayVM, TMatrix &ChargeM, TMatrix &EroverEzM,
02799 const Int_t ITERATIONS )
02800 {
02801
02802 const Int_t ROWS = ArrayVM.GetNrows() ;
02803 const Int_t COLUMNS = ArrayVM.GetNcols() ;
02804 const Float_t GRIDSIZER = (OFCRadius-IFCRadius) / (ROWS-1) ;
02805 const Float_t GRIDSIZEZ = TPC_Z0 / (COLUMNS-1) ;
02806 const Float_t Ratio = GRIDSIZER*GRIDSIZER / (GRIDSIZEZ*GRIDSIZEZ) ;
02807
02808
02809
02810
02811 if ( !IsPowerOfTwo(ROWS-1) )
02812 { cout << "StMagUtilities::PoissonRelaxation - Error in the number of ROWS. Must be 2**M - 1" << endl ; exit(1) ; }
02813 if ( !IsPowerOfTwo(COLUMNS-1) )
02814 { cout << "StMagUtilities::PoissonRelaxation - Error in the number of COLUMNS. Must be 2**N - 1" << endl ; exit(1) ; }
02815
02816
02817 Float_t *ArrayE,*ArrayV,*Charge,*SumCharge,*EroverEz ;
02818
02819 TMatrix ArrayEM(ROWS,COLUMNS) ;
02820 TMatrix SumChargeM(ROWS,COLUMNS) ;
02821 ArrayE = ArrayEM.GetMatrixArray() ;
02822 SumCharge = SumChargeM.GetMatrixArray() ;
02823 ArrayV = ArrayVM.GetMatrixArray() ;
02824 Charge = ChargeM.GetMatrixArray() ;
02825 EroverEz = EroverEzM.GetMatrixArray() ;
02826
02827
02828
02829
02830
02831 Int_t i_one = (ROWS-1)/4 ;
02832 Int_t j_one = (COLUMNS-1)/4 ;
02833 Int_t loops = 1 + (int) ( 0.5 + TMath::Log2( (double) TMath::Max(i_one,j_one) ) ) ;
02834
02835 for ( Int_t count = 0 ; count < loops ; count++ ) {
02836
02837
02838
02839
02840
02841 Int_t one__ = i_one*COLUMNS;
02842 Int_t half__ = one__ / 2;
02843 Int_t half = j_one / 2;
02844
02845 Float_t tempGRIDSIZER = GRIDSIZER * i_one ;
02846 Float_t tempRatio = Ratio * i_one * i_one / ( j_one * j_one ) ;
02847 Float_t tempFourth = 1.0 / (2.0 + 2.0*tempRatio) ;
02848
02849 Float_t coef1[ROWS],coef2[ROWS];
02850 for ( Int_t i = i_one ; i < ROWS-1 ; i+=i_one ) {
02851 Float_t Radius = IFCRadius + i*GRIDSIZER ;
02852 coef1[i] = 1.0 + tempGRIDSIZER/(2*Radius);
02853 coef2[i] = 1.0 - tempGRIDSIZER/(2*Radius);
02854 }
02855
02856 for ( Int_t i = i_one ; i < ROWS-1 ; i += i_one ) {
02857 Int_t i__ = i*COLUMNS;
02858 Float_t Radius = IFCRadius + i_one*GRIDSIZER ;
02859 for ( Int_t j = j_one ; j < COLUMNS-1 ; j += j_one ) {
02860 Int_t i__j = i__ + j;
02861 if ( i_one == 1 && j_one == 1 ) SumCharge[i__j] = Charge[i__j] ;
02862 else {
02863 Float_t weight = 0.0 ;
02864 Float_t sum = 0.0 ;
02865 SumCharge[i__j]= 0.0 ;
02866 for ( Int_t ii = i-i_one/2 ; ii <= i+i_one/2 ; ii++ ) {
02867 for ( Int_t jj = j-j_one/2 ; jj <= j+j_one/2 ; jj++ ) {
02868 if ( ii == i-i_one/2 || ii == i+i_one/2 || jj == j-j_one/2 || jj == j+j_one/2 ) weight = 0.5 ;
02869 else weight = 1.0 ;
02870 SumCharge[i__j] += Charge[ii*COLUMNS+jj]*weight*Radius ;
02871 sum += weight*Radius ;
02872 }
02873 }
02874 SumCharge[i__j] /= sum ;
02875 }
02876 SumCharge[i__j] *= tempGRIDSIZER*tempGRIDSIZER;
02877 }
02878 }
02879
02880 for ( Int_t k = 1 ; k <= ITERATIONS; k++ ) {
02881
02882 Float_t OverRelax = 1.0 + TMath::Sqrt( TMath::Cos( (k*TMath::PiOver2())/ITERATIONS ) ) ;
02883 Float_t OverRelaxM1 = OverRelax - 1.0 ;
02884 Float_t OverRelaxtempFourth, OverRelaxcoef5 ;
02885 OverRelaxtempFourth = OverRelax * tempFourth ;
02886 OverRelaxcoef5 = OverRelaxM1 / OverRelaxtempFourth ;
02887
02888 for ( Int_t i = i_one ; i < ROWS-1 ; i += i_one ) {
02889 Int_t i__ = i*COLUMNS;
02890 for ( Int_t j = j_one ; j < COLUMNS-1 ; j += j_one ) {
02891 Int_t i__j = i__ + j;
02892
02893 ArrayV[i__j] = ( coef2[i] * ArrayV[i__j - one__]
02894 + tempRatio * ( ArrayV[i__j - j_one] + ArrayV[i__j + j_one] )
02895 + coef1[i] * ArrayV[i__j + one__]
02896 + SumCharge[i__j]
02897 ) * OverRelaxtempFourth
02898 - OverRelaxM1 * ArrayV[i__j] ;
02899
02900 }
02901 }
02902
02903 if ( k == ITERATIONS ) {
02904 for ( Int_t i = i_one ; i < ROWS-1 ; i += i_one ) {
02905 Int_t i__ = i*COLUMNS;
02906 for ( Int_t j = j_one ; j < COLUMNS-1 ; j += j_one ) {
02907 Int_t i__j = i__ + j;
02908
02909 if ( i_one > 1 ) {
02910 ArrayV[i__j + half__] = ( ArrayV[i__j + one__] + ArrayV[i__j] ) / 2 ;
02911 if ( i == i_one )
02912 ArrayV[i__j - half__] = ( ArrayV[j] + ArrayV[one__ + j] ) / 2 ;
02913 }
02914 if ( j_one > 1 ) {
02915 ArrayV[i__j + half] = ( ArrayV[i__j + j_one] + ArrayV[i__j] ) / 2 ;
02916 if ( j == j_one )
02917 ArrayV[i__j - half] = ( ArrayV[i__] + ArrayV[i__ + j_one] ) / 2 ;
02918
02919 if ( i_one > 1 ) {
02920 ArrayV[i__j + half__ + half] = ( ArrayV[i__j + one__ + j_one] + ArrayV[i__j] ) / 2 ;
02921 if ( i == i_one )
02922 ArrayV[i__j - half__ - half] = ( ArrayV[j - j_one] + ArrayV[one__ + j] ) / 2 ;
02923 if ( j == j_one )
02924 ArrayV[i__j - half__ - half] = ( ArrayV[i__ - one__] + ArrayV[i__ + j_one] ) / 2 ;
02925
02926 }
02927 }
02928 }
02929 }
02930 }
02931
02932 }
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947 i_one = i_one / 2 ; if ( i_one < 1 ) i_one = 1 ;
02948 j_one = j_one / 2 ; if ( j_one < 1 ) j_one = 1 ;
02949
02950 }
02951
02952 Float_t coef10,coef12 ;
02953 coef10 = -0.5 / GRIDSIZER ;
02954 coef12 = (GRIDSIZEZ/3.0) / (-1*StarMagE) ;
02955
02956 Int_t one__ = COLUMNS;
02957
02958
02959
02960
02961 for ( Int_t j = COLUMNS-1 ; j >= 0 ; j-- )
02962 {
02963
02964 for ( Int_t i = 1 ; i < ROWS-1 ; i++ ) {
02965 Int_t i__j = i*COLUMNS + j;
02966 ArrayE[i__j] = coef10 * ( ArrayV[i__j + one__] - ArrayV[i__j - one__] ) ;
02967 }
02968 Int_t r__j = (ROWS-1)*one__ + j;
02969 ArrayE[j] = coef10 * ( - ArrayV[2*one__ + j] + 4*ArrayV[one__ + j] - 3*ArrayV[j] ) ;
02970 ArrayE[r__j] = coef10 * ( 3*ArrayV[r__j] - 4*ArrayV[r__j - one__] + ArrayV[r__j - 2*one__] ) ;
02971
02972 for ( Int_t i = 0 ; i < ROWS ; i++ )
02973 {
02974 Int_t Index = 1 ;
02975 Int_t i__ = i*COLUMNS;
02976 Int_t i__j = i__ + j;
02977 Int_t i__c = i__ + COLUMNS-1;
02978 EroverEz[i__j] = 0.0 ;
02979 if ( j == COLUMNS-2 ) EroverEz[i__j] = coef12 * 1.5 * (ArrayE[i__c - 1] + ArrayE[i__c]) ;
02980 else if ( j != COLUMNS-1 )
02981 {
02982 for ( Int_t k = i__j ; k <= i__c ; k++ )
02983 {
02984 EroverEz[i__j] += Index*ArrayE[k] ;
02985 if ( Index != 4 ) Index = 4; else Index = 2 ;
02986 }
02987 if ( Index == 4 ) EroverEz[i__j] -= ArrayE[i__c] ;
02988 else if ( Index == 2 ) EroverEz[i__j] += (0.5*ArrayE[i__c - 1] - 2.5*ArrayE[i__c]) ;
02989 EroverEz[i__j] *= coef12 ;
02990 }
02991 }
02992 }
02993
02994 }
02995
02996
02997
02998
02999
03001
03015 void StMagUtilities::Poisson3DRelaxation( TMatrix **ArrayofArrayV, TMatrix **ArrayofCharge, TMatrix **ArrayofEroverEz,
03016 TMatrix **ArrayofEPhioverEz,
03017 const Int_t PHISLICES, const Float_t DELTAPHI,
03018 const Int_t ITERATIONS, const Int_t SYMMETRY )
03019 {
03020
03021 const Int_t ROWS = ArrayofArrayV[0]->GetNrows();
03022 const Int_t COLUMNS = ArrayofArrayV[0]->GetNcols();
03023 const Float_t GRIDSIZEPHI = DELTAPHI ;
03024 const Float_t GRIDSIZER = (OFCRadius-IFCRadius) / (ROWS-1) ;
03025 const Float_t GRIDSIZEZ = TPC_Z0 / (COLUMNS-1) ;
03026 const Float_t RatioPhi = GRIDSIZER*GRIDSIZER / (GRIDSIZEPHI*GRIDSIZEPHI) ;
03027 const Float_t RatioZ = GRIDSIZER*GRIDSIZER / (GRIDSIZEZ*GRIDSIZEZ) ;
03028
03029
03030
03031 if ( !IsPowerOfTwo((ROWS-1)) )
03032 { cout << "StMagUtilities::Poisson3DRelaxation - Error in the number of ROWS. Must be 2**M - 1" << endl ; exit(1) ; }
03033 if ( !IsPowerOfTwo((COLUMNS-1)) )
03034 { cout << "StMagUtilities::Poisson3DRelaxation - Error in the number of COLUMNS. Must be 2**N - 1" << endl ; exit(1) ; }
03035 if ( PHISLICES <= 3 )
03036 { cout << "StMagUtilities::Poisson3DRelaxation - Error in the number of PHISLICES. Must be larger than 3" << endl ; exit(1) ; }
03037
03038
03039 Float_t *ArrayE,*ArrayV,*ArrayVM,*ArrayVP,*Charge,*SumCharge,*EroverEz,*EPhioverEz ;
03040
03041 TMatrix ArrayEM(ROWS,COLUMNS) ;
03042 ArrayE = ArrayEM.GetMatrixArray() ;
03043
03044
03045
03046
03047
03048 Int_t loops, m_plus, m_minus ;
03049 Int_t i_one = (ROWS-1)/4 ;
03050 Int_t j_one = (COLUMNS-1)/4 ;
03051 loops = TMath::Max(i_one, j_one) ;
03052 loops = 1 + (int) ( 0.5 + TMath::Log2((double)loops) ) ;
03053
03054 TMatrix *ArrayofSumCharge[1000] ;
03055 if ( PHISLICES > 1000 ) { cout << "StMagUtilities::Poisson3D PHISLICES > 1000 is not allowed (nor wise) " << endl ; exit(1) ; }
03056 for ( Int_t i = 0 ; i < PHISLICES ; i++ ) { ArrayofSumCharge[i] = new TMatrix(ROWS,COLUMNS) ; }
03057 Float_t OverRelaxers[ITERATIONS];
03058 for ( Int_t k = 1 ; k <= ITERATIONS; k++ ) {
03059 OverRelaxers[k-1] = 1.0 + TMath::Sqrt( TMath::Cos( (k*TMath::PiOver2())/ITERATIONS ) ) ;
03060 }
03061
03062 for ( Int_t count = 0 ; count < loops ; count++ ) {
03063
03064
03065
03066
03067
03068 Int_t one__ = i_one*COLUMNS;
03069 Int_t half__ = one__ / 2;
03070 Int_t half = j_one / 2;
03071
03072 Float_t tempGRIDSIZER = GRIDSIZER * i_one ;
03073 Float_t tempRatioPhi = RatioPhi * i_one * i_one ;
03074 Float_t tempRatioZ = RatioZ * i_one * i_one / ( j_one * j_one ) ;
03075
03076 Float_t coef1[ROWS],coef2[ROWS],coef3[ROWS],coef4[ROWS];
03077 for ( Int_t i = i_one ; i < ROWS-1 ; i+=i_one ) {
03078 Float_t Radius = IFCRadius + i*GRIDSIZER ;
03079 coef1[i] = 1.0 + tempGRIDSIZER/(2*Radius);
03080 coef2[i] = 1.0 - tempGRIDSIZER/(2*Radius);
03081 coef3[i] = tempRatioPhi/(Radius*Radius);
03082 coef4[i] = 0.5 / (1.0 + tempRatioZ + coef3[i]);
03083 }
03084
03085 for ( Int_t m = 0 ; m < PHISLICES ; m++ ) {
03086 Charge = ArrayofCharge[m]->GetMatrixArray() ;
03087 SumCharge = ArrayofSumCharge[m]->GetMatrixArray() ;
03088 for ( Int_t i = i_one ; i < ROWS-1 ; i += i_one ) {
03089 Int_t i__ = i*COLUMNS;
03090 Float_t Radius = IFCRadius + i*GRIDSIZER ;
03091 for ( Int_t j = j_one ; j < COLUMNS-1 ; j += j_one ) {
03092 Int_t i__j = i__ + j;
03093 if ( i_one == 1 && j_one == 1 ) SumCharge[i__j] = Charge[i__j] ;
03094 else {
03095 Float_t weight = 0.0 ;
03096 Float_t sum = 0.0 ;
03097 SumCharge[i__j]= 0.0 ;
03098 for ( Int_t ii = i-i_one/2 ; ii <= i+i_one/2 ; ii++ ) {
03099 for ( Int_t jj = j-j_one/2 ; jj <= j+j_one/2 ; jj++ ) {
03100 if ( ii == i-i_one/2 || ii == i+i_one/2 || jj == j-j_one/2 || jj == j+j_one/2 ) weight = 0.5 ;
03101 else weight = 1.0 ;
03102 SumCharge[i__j] += Charge[ii*COLUMNS+jj]*weight*Radius ;
03103 sum += weight*Radius ;
03104 }
03105 }
03106 SumCharge[i__j] /= sum ;
03107 }
03108 SumCharge[i__j] *= tempGRIDSIZER*tempGRIDSIZER;
03109 }
03110 }
03111 }
03112
03113 for ( Int_t k = 1 ; k <= ITERATIONS; k++ ) {
03114 Float_t OverRelax = OverRelaxers[k-1];
03115 Float_t OverRelaxM1 = OverRelax - 1.0 ;
03116 Float_t OverRelaxcoef4[ROWS] ;
03117 for ( Int_t i = i_one ; i < ROWS-1 ; i+=i_one ) {
03118 OverRelaxcoef4[i] = OverRelax * coef4[i] ;
03119 }
03120
03121
03122 for ( Int_t m = 0 ; m < PHISLICES ; m++ ) {
03123
03124 m_plus = m + 1;
03125 m_minus = m - 1 ;
03126 if (SYMMETRY==1) {
03127 if ( m_plus > PHISLICES-1 ) m_plus = PHISLICES - 2 ;
03128 if ( m_minus < 0 ) m_minus = 1 ;
03129 }
03130 else {
03131 if ( m_plus > PHISLICES-1 ) m_plus = 0 ;
03132 if ( m_minus < 0 ) m_minus = PHISLICES - 1 ;
03133 }
03134 ArrayV = ArrayofArrayV[m]->GetMatrixArray();
03135 ArrayVP = ArrayofArrayV[m_plus]->GetMatrixArray();
03136 ArrayVM = ArrayofArrayV[m_minus]->GetMatrixArray();
03137 SumCharge = ArrayofSumCharge[m]->GetMatrixArray() ;
03138 for ( Int_t i = i_one ; i < ROWS-1 ; i+=i_one ) {
03139 Int_t i__ = i*COLUMNS;
03140 for ( Int_t j = j_one ; j < COLUMNS-1 ; j+=j_one ) {
03141 Int_t i__j = i__ + j;
03142
03143 ArrayV[i__j] = ( coef2[i] * ArrayV[i__j - one__]
03144 + tempRatioZ * ( ArrayV[i__j - j_one] + ArrayV[i__j + j_one] )
03145 + coef1[i] * ArrayV[i__j + one__]
03146 + coef3[i] * ( ArrayVP[i__j] + ArrayVM[i__j] )
03147 + SumCharge[i__j]
03148 ) * OverRelaxcoef4[i]
03149 - OverRelaxM1*ArrayV[i__j] ;
03150
03151 }
03152 }
03153
03154 if ( k == ITERATIONS && ( i_one > 1 || j_one > 1 ) ) {
03155 for ( Int_t i = i_one ; i < ROWS-1 ; i+=i_one ) {
03156 Int_t i__ = i*COLUMNS;
03157 for ( Int_t j = j_one ; j < COLUMNS-1 ; j+=j_one ) {
03158 Int_t i__j = i__ + j;
03159
03160 if ( i_one > 1 ) {
03161 ArrayV[i__j + half__] = ( ArrayV[i__j + one__] + ArrayV[i__j] ) / 2 ;
03162 if ( i == i_one )
03163 ArrayV[i__j - half__] = ( ArrayV[j] + ArrayV[one__ + j] ) / 2 ;
03164 }
03165
03166 if ( j_one > 1 ) {
03167 ArrayV[i__j + half] = ( ArrayV[i__j + j_one] + ArrayV[i__j] ) / 2 ;
03168 if ( j == j_one )
03169 ArrayV[i__j - half] = ( ArrayV[i__] + ArrayV[i__ + j_one] ) / 2 ;
03170
03171 if ( i_one > 1 ) {
03172 ArrayV[i__j + half__ + half] = ( ArrayV[i__j + one__ + j_one] + ArrayV[i__j] ) / 2 ;
03173 if ( i == i_one )
03174 ArrayV[i__j - half__ - half] = ( ArrayV[j - j_one] + ArrayV[one__ + j] ) / 2 ;
03175 if ( j == j_one )
03176 ArrayV[i__j - half__ - half] = ( ArrayV[i__ - one__] + ArrayV[i__ + j_one] ) / 2 ;
03177
03178 }
03179 }
03180 }
03181 }
03182 }
03183
03184 }
03185 }
03186
03187 i_one = i_one / 2 ; if ( i_one < 1 ) i_one = 1 ;
03188 j_one = j_one / 2 ; if ( j_one < 1 ) j_one = 1 ;
03189
03190 }
03191
03192
03193 Float_t coef10,coef11,coef12 ;
03194 coef10 = -0.5 / GRIDSIZER ;
03195 coef11 = -0.5 / GRIDSIZEPHI ;
03196 coef12 = (GRIDSIZEZ/3.0) / (-1*StarMagE) ;
03197
03198 Int_t one__ = COLUMNS;
03199
03200
03201
03202
03203 for ( Int_t m = 0 ; m < PHISLICES ; m++ )
03204 {
03205 ArrayV = ArrayofArrayV[m]->GetMatrixArray();
03206 EroverEz = ArrayofEroverEz[m]->GetMatrixArray();
03207
03208 for ( Int_t j = COLUMNS-1 ; j >= 0 ; j-- )
03209 {
03210
03211 for ( Int_t i = 1 ; i < ROWS-1 ; i++ ) {
03212 Int_t i__j = i*COLUMNS + j;
03213 ArrayE[i__j] = coef10 * ( ArrayV[i__j + one__] - ArrayV[i__j - one__] ) ;
03214 }
03215 Int_t r__j = (ROWS-1)*one__ + j;
03216 ArrayE[j] = coef10 * ( - ArrayV[2*one__ + j] + 4*ArrayV[one__ + j] - 3*ArrayV[j] ) ;
03217 ArrayE[r__j] = coef10 * ( 3*ArrayV[r__j] - 4*ArrayV[r__j - one__] + ArrayV[r__j - 2*one__] ) ;
03218
03219 for ( Int_t i = 0 ; i < ROWS ; i++ )
03220 {
03221 Int_t Index = 1 ;
03222 Int_t i__ = i*COLUMNS;
03223 Int_t i__j = i__ + j;
03224 Int_t i__c = i__ + COLUMNS-1;
03225 EroverEz[i__j] = 0.0;
03226 if ( j == COLUMNS-2 ) EroverEz[i__j] = coef12 * 1.5 * (ArrayE[i__c - 1] + ArrayE[i__c]) ;
03227 else if ( j != COLUMNS-1 )
03228 {
03229 for ( Int_t k = i__j ; k <= i__c ; k++ )
03230 {
03231 EroverEz[i__j] += Index*ArrayE[k] ;
03232 if ( Index != 4 ) Index = 4; else Index = 2 ;
03233 }
03234 if ( Index == 4 ) EroverEz[i__j] -= ArrayE[i__c] ;
03235 else if ( Index == 2 ) EroverEz[i__j] += (0.5*ArrayE[i__c - 1] - 2.5*ArrayE[i__c]) ;
03236 EroverEz[i__j] *= coef12 ;
03237 }
03238 }
03239 }
03240
03241
03242 }
03243
03244
03245
03246
03247 for ( Int_t m = 0 ; m < PHISLICES ; m++ )
03248 {
03249 m_plus = m + 1;
03250 m_minus = m - 1 ;
03251 if (SYMMETRY==1) {
03252 if ( m_plus > PHISLICES-1 ) m_plus = PHISLICES - 2 ;
03253 if ( m_minus < 0 ) m_minus = 1 ;
03254 }
03255 else {
03256 if ( m_plus > PHISLICES-1 ) m_plus = 0 ;
03257 if ( m_minus < 0 ) m_minus = PHISLICES - 1 ;
03258 }
03259 ArrayVP = ArrayofArrayV[m_plus]->GetMatrixArray() ;
03260 ArrayVM = ArrayofArrayV[m_minus]->GetMatrixArray() ;
03261 EPhioverEz = ArrayofEPhioverEz[m]->GetMatrixArray() ;
03262 for ( Int_t j = COLUMNS-1 ; j >= 0 ; j-- )
03263 {
03264
03265 for ( Int_t i = 0 ; i < ROWS ; i++ )
03266 {
03267 Int_t i__j = i*COLUMNS + j;
03268 Float_t Radius = IFCRadius + i*GRIDSIZER ;
03269 ArrayE[i__j] = coef11 * ( ArrayVP[i__j] - ArrayVM[i__j] ) / Radius ;
03270 }
03271
03272 for ( Int_t i = 0 ; i < ROWS ; i++ )
03273 {
03274 Int_t i__ = i*COLUMNS;
03275 Int_t i__j = i__ + j;
03276 Int_t i__c = i__ + COLUMNS-1;
03277 Int_t Index = 1 ;
03278 EPhioverEz[i__j] = 0.0 ;
03279 if ( j == COLUMNS-2 ) EPhioverEz[i__j] = coef12 * 1.5 * (ArrayE[i__c - 1] + ArrayE[i__c]) ;
03280 else if ( j != COLUMNS-1 )
03281 {
03282 for ( Int_t k = i__j ; k <= i__c ; k++ )
03283 {
03284 EPhioverEz[i__j] += Index*ArrayE[k] ;
03285 if ( Index != 4 ) Index = 4; else Index = 2 ;
03286 }
03287 if ( Index == 4 ) EPhioverEz[i__j] -= ArrayE[i__c] ;
03288 else if ( Index == 2 ) EPhioverEz[i__j] += (0.5*ArrayE[i__c - 1] - 2.5*ArrayE[i__c]) ;
03289 EPhioverEz[i__j] *= coef12 ;
03290 }
03291 }
03292 }
03293
03294
03295 }
03296
03297
03298 for ( Int_t m = 0 ; m < PHISLICES ; m++ )
03299 {
03300 ArrayofSumCharge[m] -> Delete() ;
03301 }
03302
03303 }
03304
03305
03306
03307
03309
03338 void StMagUtilities::FixSpaceChargeDistortion ( const Int_t Charge, const Float_t x[3], const Float_t p[3],
03339 const Prime PrimaryOrGlobal, Float_t x_new[3], Float_t p_new[3],
03340 const unsigned int RowMask1 , const unsigned int RowMask2 ,const Float_t VertexError)
03341 {
03342
03343 x_new[0] = x[0] ; x_new[1] = x[1] ; x_new[2] = x[2] ;
03344 p_new[0] = p[0] ; p_new[1] = p[1] ; p_new[2] = p[2] ;
03345
03346
03347 if ( finite((double)Charge)*finite(x[0])*finite(x[1])*finite(x[2])*finite(p[0])*finite(p[1])*finite(p[2]) == 0 ) return ;
03348
03349 const Int_t INNER8 = 8 ;
03350 const Int_t INNER = 13 ;
03351 const Int_t ROWS = 45 ;
03352 const Float_t TestRadius = 77.00 ;
03353
03354 Int_t ChargeB ;
03355 Float_t B[3], Rotation, Direction, xx[3], xxprime[3] ;
03356 Double_t Xtrack[ROWS], Ytrack[ROWS], Ztrack[ROWS] ;
03357 Double_t Xtrack1[ROWS], Ytrack1[ROWS], Ztrack1[ROWS] ;
03358 Double_t R[ROWS], dX[ROWS], dY[ROWS], C0, X0, Y0, R0, Pt, R2, theta, theta0, DeltaTheta ;
03359 Double_t Xprime[ROWS+1], Yprime[ROWS+1], eX[ROWS+1], eY[ROWS+1] ;
03360
03361 BField(x,B) ;
03362 ChargeB = Charge * TMath::Sign((int)1,(int)(B[2]*1000)) ;
03363 Pt = TMath::Sqrt( p[0]*p[0] + p[1]*p[1] ) ;
03364 R0 = TMath::Abs( 1000.0 * Pt / ( 0.299792 * B[2] ) ) ;
03365 X0 = x[0] + ChargeB * p[1] * R0 / Pt ;
03366 Y0 = x[1] - ChargeB * p[0] * R0 / Pt ;
03367 Rotation = TMath::Sign( (double)1.0, (x[0]-X0)*p[1] - (x[1]-Y0)*p[0] ) ;
03368
03369 for ( Int_t i = 0 ; i < ROWS ; i++ )
03370 {
03371 if ( i < INNER8 )
03372 R[i] = 60.0 + i*4.8 ;
03373 else if ( i < INNER )
03374 R[i] = 93.6 + (i-INNER8+1)*5.2 ;
03375 else
03376 R[i] = 127.195 + (i-INNER)*2.0 ;
03377 }
03378
03379 if (Y0 == 0.0) Direction = TMath::Sign((float)1.0,p[1]) ;
03380 else
03381 {
03382 Direction = 1.0 ;
03383 R2 = TestRadius * TestRadius ;
03384 C0 = ( R2 - R0*R0 + X0*X0 + Y0*Y0 ) ;
03385 Double_t X1 = 0.5 * ( C0*X0 - TMath::Sqrt( TMath::Abs( C0*C0*X0*X0 - (C0*C0 - 4*Y0*Y0*R2) * (X0*X0+Y0*Y0) ) ) ) / (X0*X0 + Y0*Y0) ;
03386 Double_t Y1 = ( R2 - R0*R0 - 2*X0*X1 + X0*X0 + Y0*Y0 ) / ( 2 * Y0 ) ;
03387 Double_t X2 = 0.5 * ( C0*X0 + TMath::Sqrt( TMath::Abs( C0*C0*X0*X0 - (C0*C0 - 4*Y0*Y0*R2) * (X0*X0+Y0*Y0) ) ) ) / (X0*X0 + Y0*Y0) ;
03388 Double_t Y2 = ( R2 - R0*R0 - 2*X0*X2 + X0*X0 + Y0*Y0 ) / ( 2 * Y0 ) ;
03389 if ( X2*p[0] + Y2*p[1] < X1*p[0] + Y1*p[1] ) Direction = -1.0 ;
03390 }
03391
03392 theta0 = TMath::ATan2( (x[1]-Y0) , (x[0]-X0) ) ;
03393 Xprime[0] = theta0 ;
03394 Yprime[0] = 0.0 ;
03395 eX[0] = 0.5 / R0 ;
03396 eY[0] = VertexError ;
03397
03398 Int_t index = -1 ;
03399 unsigned int OneBit = 1 ;
03400 for ( Int_t i = 0 ; i < ROWS ; i++ )
03401 {
03402 if ( ( i < 24 ) && ( ( RowMask1 & OneBit<<(i+8) ) == 0 ) ) continue ;
03403 if ( ( i >= 24 ) && ( ( RowMask2 & OneBit<<(i-24) ) == 0 ) ) continue ;
03404 index++ ;
03405 C0 = ( R[i]*R[i] - R0*R0 + X0*X0 + Y0*Y0 ) ;
03406 if (Y0 == 0.0) Xtrack[index] = 0.5 * C0 / X0 ;
03407 else Xtrack[index] = 0.5*( C0*X0 + Direction*TMath::Sqrt( TMath::Abs( C0*C0*X0*X0 - (C0*C0-4*Y0*Y0*R[i]*R[i])*(X0*X0+Y0*Y0) )) )
03408 / (X0*X0+Y0*Y0) ;
03409 if (Y0 == 0.0) Ytrack[index] = Direction * TMath::Sqrt( TMath::Abs( R[i]*R[i] - Xtrack[index]*Xtrack[index] ) ) ;
03410 else Ytrack[index] = ( R[i]*R[i] - R0*R0 - 2*X0*Xtrack[index] + X0*X0 + Y0*Y0 ) / ( 2 * Y0 ) ;
03411 DeltaTheta = TMath::ATan2(x[1]-Y0,x[0]-X0) - TMath::ATan2(Ytrack[index]-Y0,Xtrack[index]-X0) ;
03412 while ( DeltaTheta < -1*TMath::Pi() ) DeltaTheta += TMath::TwoPi() ;
03413 while ( DeltaTheta >= TMath::Pi() ) DeltaTheta -= TMath::TwoPi() ;
03414 Ztrack[index] = x[2] - Rotation*DeltaTheta*R0*p[2] / Pt ;
03415 xx[0] = Xtrack[index] ; xx[1] = Ytrack[index] ; xx[2] = Ztrack[index] ;
03416 UndoSpaceChargeDistortion(xx,xxprime) ;
03417 xx[0] = Xtrack[index] - (xxprime[0]-xx[0]) ; xx[1] = Ytrack[index] - (xxprime[1]-xx[1]) ; xx[2] = Ztrack[index] - (xxprime[2]-xx[2]) ;
03418 UndoSpaceChargeR2Distortion(xx,xxprime) ;
03419 Xtrack1[index] = xxprime[0] ; Ytrack1[index] = xxprime[1] ; Ztrack1[index] = xxprime[2] ;
03420 theta = TMath::ATan2( (Ytrack[index]-Y0) , (Xtrack[index]-X0) ) ;
03421 while ( (theta - theta0) < -1*TMath::Pi() ) theta = theta + 2*TMath::Pi() ;
03422 while ( (theta - theta0) >= TMath::Pi() ) theta = theta - 2*TMath::Pi() ;
03423 dX[index] = Xtrack1[index] - Xtrack[index] ;
03424 dY[index] = Ytrack1[index] - Ytrack[index] ;
03425 Xprime[index+1] = theta ;
03426 Yprime[index+1] = dY[index]*TMath::Sin(theta) + dX[index]*TMath::Cos(theta) ;
03427 eX[index+1] = 0.5 / R0 ;
03428 eY[index+1] = 0.0100 ;
03429 }
03430 if ( index == -1 ) return ;
03431
03432 TGraphErrors gre(index-PrimaryOrGlobal+2,&Xprime[PrimaryOrGlobal],&Yprime[PrimaryOrGlobal],&eX[PrimaryOrGlobal],&eY[PrimaryOrGlobal]) ;
03433 TF1 FIT("myFIT", "[0] + [1]*sin(x) + [2]*cos(x)" );
03434 FIT.SetParameter( 0, 0. );
03435 FIT.SetParameter( 1, 0. );
03436 FIT.SetParameter( 2, 0. );
03437 gre.Fit("myFIT","NQ") ;
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457 Double_t X0_new = X0 + FIT.GetParameter( 2 ) ;
03458 Double_t Y0_new = Y0 + FIT.GetParameter( 1 ) ;
03459 Double_t R0_new = R0 + FIT.GetParameter( 0 ) ;
03460 Double_t Pt_new = TMath::Abs( R0_new * 0.299792 * B[2] / 1000. ) ;
03461
03462 if ( TMath::Sqrt( x[0]*x[0]+x[1]*x[1] ) <= IFCRadius )
03463 { x_new[0] = x[0] ; x_new[1] = x[1] ; x_new[2] = x[2] ; }
03464 else
03465 {
03466 UndoSpaceChargeDistortion(x,xxprime) ;
03467 xx[0] = x[0] - (xxprime[0]-x[0]) ; xx[1] = x[1] - (xxprime[1]-x[1]) ; xx[2] = x[2] - (xxprime[2]-x[2]) ;
03468 UndoSpaceChargeR2Distortion(xx,x_new) ;
03469 }
03470
03471 Int_t count = 0 ; p_new[2] = 0.0 ;
03472 for ( Int_t i = 0 ; i < index+1 ; i++ )
03473 {
03474 DeltaTheta = (TMath::ATan2(Ytrack1[i]-Y0_new,Xtrack1[i]-X0_new)-TMath::ATan2(x_new[1]-Y0_new,x_new[0]-X0_new)) ;
03475 while ( DeltaTheta < -1*TMath::Pi() ) DeltaTheta += TMath::TwoPi() ;
03476 while ( DeltaTheta >= TMath::Pi() ) DeltaTheta -= TMath::TwoPi() ;
03477 if ( DeltaTheta != 0 ) { p_new[2] += (Ztrack1[i]-x_new[2]) / DeltaTheta ; count += 1 ; }
03478 }
03479
03480 p_new[0] = Pt_new * ( x_new[1] - Y0_new ) / ( ChargeB * R0_new ) ;
03481 p_new[1] = Pt_new * ( X0_new - x_new[0] ) / ( ChargeB * R0_new ) ;
03482 p_new[2] *= Pt_new / ( Rotation * R0_new * count ) ;
03483
03484 }
03485
03486
03487
03488
03489
03490
03492
03520 void StMagUtilities::ApplySpaceChargeDistortion (const Double_t sc, const Int_t Charge, const Float_t x[3], const Float_t p[3],
03521 const Prime PrimaryOrGlobal, Int_t &new_Charge, Float_t x_new[3], Float_t p_new[3],
03522 const unsigned int RowMask1, const unsigned int RowMask2, const Float_t VertexError )
03523 {
03524
03525 x_new[0] = x[0] ; x_new[1] = x[1] ; x_new[2] = x[2] ;
03526 p_new[0] = p[0] ; p_new[1] = p[1] ; p_new[2] = p[2] ;
03527
03528
03529 if ( finite((double)Charge)*finite(x[0])*finite(x[1])*finite(x[2])*finite(p[0])*finite(p[1])*finite(p[2]) == 0 ) return ;
03530
03531 const Float_t InnerOuterRatio = 0.6 ;
03532 const Int_t INNER8 = 8 ;
03533 const Int_t INNER = 13 ;
03534 const Int_t ROWS = 45 ;
03535 const Int_t RefIndex = 7 ;
03536 const Int_t MinHits = 15 ;
03537 const Int_t DEBUG = 0 ;
03538
03539 Int_t ChargeB ;
03540 Float_t B[3], Direction, xx[3], xxprime[3] ;
03541 Double_t Xreference, Yreference ;
03542 Double_t Xtrack[ROWS], Ytrack[ROWS], Ztrack[ROWS] ;
03543 Double_t R[ROWS], C0, X0, Y0, R0, Pt, R2, DeltaTheta, DCA ;
03544 Double_t Xprime[ROWS+1], Yprime[ROWS+1], Zprime[ROWS+1], dX[ROWS+1], dY[ROWS+1] ;
03545 Double_t U[ROWS+1], V[ROWS+1], eU[ROWS+1], eV[ROWS+1] ;
03546
03547
03548
03549 StDetectorDbSpaceChargeR2* tempfSpaceChargeR2 = fSpaceChargeR2 ;
03550 Double_t tempSpaceChargeR2 = SpaceChargeR2 ;
03551 ManualSpaceChargeR2(sc,SpaceChargeEWRatio);
03552
03553 BField(x,B) ;
03554 ChargeB = Charge * TMath::Sign((int)1,(int)(B[2]*1000)) ;
03555 Pt = TMath::Sqrt( p[0]*p[0] + p[1]*p[1] ) ;
03556 R0 = TMath::Abs( 1000.0 * Pt / ( 0.299792 * B[2] ) ) ;
03557 X0 = x[0] + ChargeB * p[1] * R0 / Pt ;
03558 Y0 = x[1] - ChargeB * p[0] * R0 / Pt ;
03559 DCA = TMath::Sqrt( X0*X0 + Y0*Y0 ) - R0 ;
03560
03561 for ( Int_t i = 0 ; i < ROWS ; i++ )
03562 {
03563 if ( i < INNER8 )
03564 R[i] = 60.0 + i*4.8 ;
03565 else if ( i < INNER )
03566 R[i] = 93.6 + (i-INNER8+1)*5.2 ;
03567 else
03568 R[i] = 127.195 + (i-INNER)*2.0 ;
03569 }
03570
03571
03572 if (TMath::Abs(Y0) < 0.001 ) Direction = TMath::Sign( (float)1.0, p[1] ) ;
03573 else
03574 {
03575 Direction = 1.0 ;
03576 R2 = R[RefIndex]*R[RefIndex] ;
03577 C0 = ( R2 - R0*R0 + X0*X0 + Y0*Y0 ) ;
03578 Double_t X1 = 0.5 * ( C0*X0 - TMath::Sqrt( TMath::Abs( C0*C0*X0*X0 - (C0*C0 - 4*Y0*Y0*R2) * (X0*X0+Y0*Y0) ) ) )
03579 / (X0*X0 + Y0*Y0) ;
03580 Double_t Y1 = ( R2 - R0*R0 - 2*X0*X1 + X0*X0 + Y0*Y0 ) / ( 2 * Y0 ) ;
03581 Double_t X2 = 0.5 * ( C0*X0 + TMath::Sqrt( TMath::Abs( C0*C0*X0*X0 - (C0*C0 - 4*Y0*Y0*R2) * (X0*X0+Y0*Y0) ) ) )
03582 / (X0*X0 + Y0*Y0) ;
03583 Double_t Y2 = ( R2 - R0*R0 - 2*X0*X2 + X0*X0 + Y0*Y0 ) / ( 2 * Y0 ) ;
03584 if ( X2*p[0] + Y2*p[1] < X1*p[0] + Y1*p[1] ) Direction = -1.0 ;
03585 }
03586
03587 Xreference = Yreference = 0.0 ;
03588 for ( Int_t i = 0 ; i < ROWS ; i++ )
03589 {
03590 C0 = ( R[i]*R[i] - R0*R0 + X0*X0 + Y0*Y0 ) ;
03591 if ( TMath::Abs(Y0) < 0.001 ) Xtrack[i] = 0.5 * C0 / X0 ;
03592 else Xtrack[i] = 0.5*( C0*X0 + Direction*TMath::Sqrt( TMath::Abs( C0*C0*X0*X0 -
03593 (C0*C0-4*Y0*Y0*R[i]*R[i])*(X0*X0+Y0*Y0) )) ) / (X0*X0+Y0*Y0) ;
03594 if ( TMath::Abs(Y0) < 0.001 ) Ytrack[i] = Direction * TMath::Sqrt( TMath::Abs( R[i]*R[i] - Xtrack[i]*Xtrack[i] ) ) ;
03595 else Ytrack[i] = ( R[i]*R[i] - R0*R0 - 2*X0*Xtrack[i] + X0*X0 + Y0*Y0 ) / ( 2 * Y0 ) ;
03596 DeltaTheta = TMath::ATan2(x[1]-Y0,x[0]-X0) - TMath::ATan2(Ytrack[i]-Y0,Xtrack[i]-X0) ;
03597 while ( DeltaTheta < -1*TMath::Pi() ) DeltaTheta += TMath::TwoPi() ;
03598 while ( DeltaTheta >= TMath::Pi() ) DeltaTheta -= TMath::TwoPi() ;
03599 Ztrack[i] = x[2] + ChargeB*DeltaTheta*R0*p[2] / Pt ;
03600 xx[0] = Xtrack[i] ; xx[1] = Ytrack[i] ; xx[2] = Ztrack[i] ;
03601
03602 UndoSpaceChargeR2Distortion(xx,xxprime) ;
03603
03604 Xtrack[i] = xxprime[0] ; Ytrack[i] = xxprime[1] ; Ztrack[i] = xxprime[2] ;
03605
03606 if ( i == RefIndex )
03607 {
03608 Xreference = Xtrack[i] ;
03609 Yreference = Ytrack[i] ;
03610 }
03611 }
03612
03613 Int_t Index = 0 ;
03614 unsigned int OneBit = 1 ;
03615 for ( Int_t i = 0 ; i < ROWS ; i++ )
03616 {
03617 if ( ( i < 24 ) && (( RowMask1 & OneBit<<(i+8) ) == 0 )) continue ;
03618 if ( ( i >= 24 ) && (( RowMask2 & OneBit<<(i-24) ) == 0 )) continue ;
03619 Index++ ;
03620 Xprime[Index] = Xtrack[i] ; Yprime[Index] = Ytrack[i] ; Zprime[Index] = Ztrack[i] ;
03621 dX[Index] = 0.2 ; dY[Index] = 1.0 ;
03622
03623 if ( i < INNER ) { dX[Index] *= InnerOuterRatio ; dY[Index] *= InnerOuterRatio ; } ;
03624 }
03625
03626
03627 Xprime[0] = x[0] ; Yprime[0] = x[1] ; Zprime[0] = x[2] ; dX[0] = VertexError ; dY[0] = VertexError ;
03628
03629
03630 Int_t count = -1 ;
03631 for ( Int_t i = PrimaryOrGlobal ; i < Index+1 ; i++ )
03632 {
03633 Double_t zero = 0.001 ;
03634 Double_t displacement2 ;
03635
03636 displacement2 =
03637 (Xprime[i]-Xreference)*(Xprime[i]-Xreference) + (Yprime[i]-Yreference)*(Yprime[i]-Yreference) ;
03638
03639 if ( displacement2 > zero )
03640 {
03641 count ++ ;
03642 U[count] = ( Xprime[i] - Xreference ) / displacement2 ;
03643 V[count] = ( Yprime[i] - Yreference ) / displacement2 ;
03644 eU[count] = dX[i] / displacement2 ;
03645 eV[count] = dY[i] / displacement2 ;
03646 }
03647 }
03648
03649 if ( count < MinHits ) return ;
03650
03651 TGraphErrors gre( count+1, U, V, eU, eV ) ;
03652 gre.Fit("pol1","Q") ;
03653 TF1 *fit = gre.GetFunction("pol1" ) ;
03654
03655 if ( DEBUG )
03656 {
03657 TCanvas* c1 = new TCanvas("A Simple Fit","The Fit", 250, 10, 700, 500) ;
03658 c1 -> cd() ;
03659 gre.Draw("A*") ;
03660 c1 -> Update() ;
03661 TCanvas* c2 = new TCanvas("The circles are OK","The circles ", 250, 800, 700, 500) ;
03662 TGraph* gra = new TGraph( Index-PrimaryOrGlobal+1, &Xprime[PrimaryOrGlobal], &Yprime[PrimaryOrGlobal] ) ;
03663 c2 -> cd() ;
03664 gra -> SetMaximum(200) ;
03665 gra -> SetMinimum(-200) ;
03666 gra -> Draw("A*") ;
03667 gra -> GetXaxis() -> SetLimits(-200.,200.) ;
03668 gra -> Draw("A*") ;
03669 c2 -> Update() ;
03670 }
03671
03672 Double_t X0_new = Xreference - ( fit->GetParameter(1) / ( 2.0 * fit->GetParameter(0) ) ) ;
03673 Double_t Y0_new = Yreference + ( 1.0 / ( 2.0 * fit->GetParameter(0) ) ) ;
03674 Double_t R0_new = TMath::Sqrt( (Xreference-X0_new)*(Xreference-X0_new) + (Yreference-Y0_new)*(Yreference-Y0_new) ) ;
03675 Double_t Pt_new = TMath::Abs ( R0_new * 0.299792 * B[2] / 1000. ) ;
03676
03677
03678
03679
03680
03681 if ( TMath::Sqrt( x[0]*x[0]+x[1]*x[1] ) <= IFCRadius )
03682 { x_new[0] = x[0] ; x_new[1] = x[1] ; x_new[2] = x[2] ; }
03683 else
03684 {
03685 UndoSpaceChargeR2Distortion(x,x_new) ;
03686 }
03687
03688 Int_t icount = 0 ; p_new[2] = 0.0 ;
03689 for ( Int_t i = 0 ; i < Index+1 ; i++ )
03690 {
03691 DeltaTheta = (TMath::ATan2(Yprime[i]-Y0_new,Xprime[i]-X0_new)-TMath::ATan2(x_new[1]-Y0_new,x_new[0]-X0_new)) ;
03692 while ( DeltaTheta < -1*TMath::Pi() ) DeltaTheta += TMath::TwoPi() ;
03693 while ( DeltaTheta >= TMath::Pi() ) DeltaTheta -= TMath::TwoPi() ;
03694 if ( DeltaTheta != 0 ) { p_new[2] += (Zprime[i]-x_new[2]) / DeltaTheta ; icount += 1 ; }
03695 }
03696
03697 p_new[0] = Pt_new * ( x_new[1] - Y0_new ) / ( ChargeB * R0_new ) ;
03698 p_new[1] = Pt_new * ( X0_new - x_new[0] ) / ( ChargeB * R0_new ) ;
03699 p_new[2] *= Pt_new / ( -1 * ChargeB * R0_new * icount ) ;
03700
03701
03702 Float_t change = TMath::Abs( TMath::ATan2(Y0,X0) - TMath::ATan2(Y0_new,X0_new) ) ;
03703 if ( change > 0.9*TMath::Pi() && change < 1.1*TMath::Pi() ) new_Charge = -1 * Charge ;
03704 else new_Charge = Charge ;
03705
03706
03707 fSpaceChargeR2 = tempfSpaceChargeR2 ;
03708 SpaceChargeR2 = tempSpaceChargeR2 ;
03709
03710 }
03711
03712
03713
03715
03719 Int_t StMagUtilities::PredictSpaceChargeDistortion (Int_t Charge, Float_t Pt, Float_t VertexZ, Float_t PseudoRapidity,
03720 Float_t DCA, const unsigned int RowMask1, const unsigned int RowMask2, Float_t &pSpace )
03721 {
03722
03723 const Int_t INNER8 = 8 ;
03724 const Int_t INNER = 13 ;
03725 const Int_t ROWS = 45 ;
03726 const Int_t RefIndex = 7 ;
03727 const Int_t MinInnerTPCHits = 5 ;
03728 const Int_t MinOuterTPCHits = 10 ;
03729 const Int_t DEBUG = 0 ;
03730
03731 unsigned int OneBit = 1 ;
03732 Int_t InnerTPCHits = 0, OuterTPCHits = 0 ;
03733 for ( Int_t i = 0 ; i < ROWS ; i++ )
03734 {
03735 if ( i < INNER )
03736 {
03737 if ( ( i < 24 ) && (( RowMask1 & OneBit<<(i+8) ) != 0 )) InnerTPCHits++ ;
03738 }
03739 else
03740 {
03741 if ( ( i < 24 ) && (( RowMask1 & OneBit<<(i+8) ) != 0 )) OuterTPCHits++ ;
03742 if ( ( i >= 24 ) && (( RowMask2 & OneBit<<(i-24) ) != 0 )) OuterTPCHits++ ;
03743 }
03744 }
03745
03746 pSpace = 0 ;
03747
03748 if ( (Pt < 0.3) || (Pt > 2.0) ) return(0) ;
03749 if ( (VertexZ < -50) || (VertexZ > 50) ) return(0) ;
03750 if ( (PseudoRapidity < -1.0) || (PseudoRapidity > 1.0) ) return(0) ;
03751 if ( (Charge != 1) && (Charge != -1) ) return(0) ;
03752 if ( (DCA < -4.0) || (DCA > 4.0) ) return(0) ;
03753 if ( InnerTPCHits < MinInnerTPCHits ) return(0) ;
03754 if ( OuterTPCHits < MinOuterTPCHits ) return(0) ;
03755
03756 Int_t ChargeB ;
03757 Float_t B[3], Direction, xx[3], xxprime[3] ;
03758 Double_t Xreference, Yreference ;
03759 Double_t Xtrack[ROWS], Ytrack[ROWS], Ztrack[ROWS] ;
03760 Double_t R[ROWS], C0, X0, Y0, R0, Pz_over_Pt, Z_coef, DeltaTheta ;
03761 Double_t Xprime[ROWS+1], Yprime[ROWS+1], Zprime[ROWS+1], dX[ROWS+1], dY[ROWS+1] ;
03762 Double_t U[ROWS+1], V[ROWS+1], eU[ROWS+1], eV[ROWS+1] ;
03763
03764
03765 StDetectorDbSpaceChargeR2* tempfSpaceChargeR2 = fSpaceChargeR2 ;
03766 Double_t tempSpaceChargeR2 = SpaceChargeR2 ;
03767 if (!useManualSCForPredict) ManualSpaceChargeR2(0.01,SpaceChargeEWRatio);
03768
03769 Float_t x[3] = { 0, 0, 0 } ;
03770 BField(x,B) ;
03771 ChargeB = Charge * TMath::Sign((int)1,(int)(B[2]*1000)) ;
03772 R0 = TMath::Abs( 1000.0 * Pt / ( 0.299792 * B[2] ) ) ;
03773 X0 = ChargeB * 0.707107 * R0 ;
03774 Y0 = ChargeB * -0.707107 * R0 ;
03775 Pz_over_Pt = TMath::SinH(PseudoRapidity) ;
03776 Z_coef = ChargeB*R0*Pz_over_Pt ;
03777
03778 for ( Int_t i = 0 ; i < ROWS ; i++ )
03779 {
03780 if ( i < INNER8 )
03781 R[i] = 60.0 + i*4.8 ;
03782 else if ( i < INNER )
03783 R[i] = 93.6 + (i-INNER8+1)*5.2 ;
03784 else
03785 R[i] = 127.195 + (i-INNER)*2.0 ;
03786 }
03787
03788 Float_t InnerOuterRatio = 0.0 ;
03789 Xreference = Yreference = 0.0 ;
03790 Direction = 1.0 ;
03791 for ( Int_t i = 0 ; i < ROWS ; i++ )
03792 {
03793 C0 = ( R[i]*R[i] - R0*R0 + X0*X0 + Y0*Y0 ) ;
03794 if ( TMath::Abs(Y0) < 0.001 ) Xtrack[i] = 0.5 * C0 / X0 ;
03795 else Xtrack[i] = 0.5*( C0*X0 + Direction*TMath::Sqrt( TMath::Abs( C0*C0*X0*X0 -
03796 (C0*C0-4*Y0*Y0*R[i]*R[i])*(X0*X0+Y0*Y0) )) ) / (X0*X0+Y0*Y0) ;
03797 if ( TMath::Abs(Y0) < 0.001 ) Ytrack[i] = Direction * TMath::Sqrt( TMath::Abs( R[i]*R[i] - Xtrack[i]*Xtrack[i] ) ) ;
03798 else Ytrack[i] = ( R[i]*R[i] - R0*R0 - 2*X0*Xtrack[i] + X0*X0 + Y0*Y0 ) / ( 2 * Y0 ) ;
03799 DeltaTheta = TMath::ATan2(-1*Y0,-1*X0) - TMath::ATan2(Ytrack[i]-Y0,Xtrack[i]-X0) ;
03800 while ( DeltaTheta < -1*TMath::Pi() ) DeltaTheta += TMath::TwoPi() ;
03801 while ( DeltaTheta >= TMath::Pi() ) DeltaTheta -= TMath::TwoPi() ;
03802 Ztrack[i] = VertexZ + DeltaTheta*Z_coef ;
03803 xx[0] = Xtrack[i] ; xx[1] = Ytrack[i] ; xx[2] = Ztrack[i] ;
03804
03805 if (mDistortionMode & kSpaceChargeR2) {
03806 UndoSpaceChargeR2Distortion ( xx, xxprime ) ;
03807 InnerOuterRatio = 1.3 ;
03808 for ( unsigned int j = 0 ; j < 3; ++j )
03809 {
03810 xx[j] = xxprime[j];
03811 }
03812 }
03813 if (mDistortionMode & kGridLeak) {
03814 UndoGridLeakDistortion ( xx, xxprime ) ;
03815 InnerOuterRatio = 0.6 ;
03816 for ( unsigned int j = 0 ; j < 3 ; ++j )
03817 {
03818 xx[j] = xxprime[j];
03819 }
03820 }
03821 if (mDistortionMode & k3DGridLeak) {
03822 Undo3DGridLeakDistortion ( xx, xxprime ) ;
03823 InnerOuterRatio = 0.6 ;
03824 for ( unsigned int j = 0 ; j < 3 ; ++j )
03825 {
03826 xx[j] = xxprime[j];
03827 }
03828 }
03829
03830 Xtrack[i] = 2*Xtrack[i] - xx[0] ;
03831 Ytrack[i] = 2*Ytrack[i] - xx[1] ;
03832 Ztrack[i] = 2*Ztrack[i] - xx[2] ;
03833
03834 if ( i == RefIndex )
03835 {
03836 Xreference = Xtrack[i] ;
03837 Yreference = Ytrack[i] ;
03838 }
03839 }
03840
03841 Int_t Index = -1 ;
03842 for ( Int_t i = 0 ; i < ROWS ; i++ )
03843 {
03844 if ( ( i < 24 ) && (( RowMask1 & OneBit<<(i+8) ) == 0 )) continue ;
03845 if ( ( i >= 24 ) && (( RowMask2 & OneBit<<(i-24) ) == 0 )) continue ;
03846 Index++ ;
03847 Xprime[Index] = Xtrack[i] ; Yprime[Index] = Ytrack[i] ; Zprime[Index] = Ztrack[i] ;
03848 dX[Index] = 0.2 ; dY[Index] = 1.0 ;
03849
03850 if ( i < INNER ) { dX[Index] *= InnerOuterRatio ; dY[Index] *= InnerOuterRatio ; } ;
03851 }
03852
03853
03854 Int_t count = -1 ;
03855 for ( Int_t i = 0 ; i < Index+1 ; i++ )
03856 {
03857 Double_t zero = 0.001 ;
03858 Double_t displacement2 ;
03859
03860 displacement2 =
03861 (Xprime[i]-Xreference)*(Xprime[i]-Xreference) + (Yprime[i]-Yreference)*(Yprime[i]-Yreference) ;
03862
03863 if ( displacement2 > zero )
03864 {
03865 count ++ ;
03866 U[count] = ( Xprime[i] - Xreference ) / displacement2 ;
03867 V[count] = ( Yprime[i] - Yreference ) / displacement2 ;
03868 eU[count] = dX[i] / displacement2 ;
03869 eV[count] = dY[i] / displacement2 ;
03870 }
03871 }
03872
03873 TGraphErrors gre( count+1, U, V, eU, eV ) ;
03874 gre.Fit("pol1","Q") ;
03875 TF1 *fit = gre.GetFunction("pol1" ) ;
03876
03877 if ( DEBUG )
03878 {
03879 TCanvas* c1 = new TCanvas("A Simple Fit","The Fit", 250, 10, 700, 500) ;
03880 c1 -> cd() ;
03881 gre.Draw("A*") ;
03882 c1 -> Update() ;
03883 TCanvas* c2 = new TCanvas("The circles are OK","The circles ", 250, 800, 700, 500) ;
03884 TGraph* gra = new TGraph( Index+1, Xprime, Yprime ) ;
03885 c2 -> cd() ;
03886 gra -> SetMaximum(200) ;
03887 gra -> SetMinimum(-200) ;
03888 gra -> Draw("A*") ;
03889 gra -> GetXaxis() -> SetLimits(-200.,200.) ;
03890 gra -> Draw("A*") ;
03891 c2 -> Update() ;
03892 }
03893
03894 Double_t X0_new = Xreference - ( fit->GetParameter(1) / ( 2.0 * fit->GetParameter(0) ) ) ;
03895 Double_t Y0_new = Yreference + ( 1.0 / ( 2.0 * fit->GetParameter(0) ) ) ;
03896 Double_t R0_new = TMath::Sqrt( (Xreference-X0_new)*(Xreference-X0_new) + (Yreference-Y0_new)*(Yreference-Y0_new) ) ;
03897 Double_t DCA_new = TMath::Sqrt( X0_new*X0_new + Y0_new*Y0_new ) - R0_new ;
03898
03899 pSpace = (DCA * ChargeB) * SpaceChargeR2 / DCA_new ;
03900
03901
03902 fSpaceChargeR2 = tempfSpaceChargeR2 ;
03903 SpaceChargeR2 = tempSpaceChargeR2 ;
03904
03905 return(1) ;
03906
03907 }
03908
03909
03911
03937 Int_t StMagUtilities::PredictSpaceChargeDistortion (Int_t Charge, Float_t Pt, Float_t VertexZ, Float_t PseudoRapidity, Float_t Phi,
03938 Float_t DCA, const unsigned int RowMask1, const unsigned int RowMask2,
03939 Float_t RowMaskErrorR[64], Float_t RowMaskErrorRPhi[64], Float_t &pSpace )
03940 {
03941
03942 const Int_t INNERDETECTORS = 6 ;
03943 const Int_t SSDLAYERS = 1 ;
03944 const Int_t INNER8 = 8 ;
03945 const Int_t INNER = 13 ;
03946 const Int_t TPCROWS = 45 ;
03947 const Int_t MinInnerTPCHits = 5 ;
03948 const Int_t MinOuterTPCHits = 10 ;
03949 const Int_t DEBUG = 0 ;
03950
03951 const Int_t TPCOFFSET = INNERDETECTORS + SSDLAYERS + 1 ;
03952 const Int_t BITS = INNERDETECTORS + TPCROWS + SSDLAYERS + 1 ;
03953
03954 unsigned int OneBit = 1 ;
03955 Int_t InnerTPCHits = 0, OuterTPCHits = 0 ;
03956 for ( Int_t i = 0 ; i < TPCROWS ; i++ )
03957 {
03958 if ( i < INNER )
03959 {
03960 if ( ( i < 24 ) && (( RowMask1 & OneBit<<(i+8) ) != 0 )) InnerTPCHits++ ;
03961 }
03962 else
03963 {
03964 if ( ( i < 24 ) && (( RowMask1 & OneBit<<(i+8) ) != 0 )) OuterTPCHits++ ;
03965 if ( ( i >= 24 ) && (( RowMask2 & OneBit<<(i-24) ) != 0 )) OuterTPCHits++ ;
03966 }
03967 }
03968
03969 pSpace = 0 ;
03970
03971 if ( (Pt < 0.3) || (Pt > 2.0) ) return(0) ;
03972 if ( (VertexZ < -50) || (VertexZ > 50) ) return(0) ;
03973 if ( (PseudoRapidity < -1.0) || (PseudoRapidity > 1.0) ) return(0) ;
03974 if ( (Charge != 1) && (Charge != -1) ) return(0) ;
03975 if ( (DCA < -4.0) || (DCA > 4.0) ) return(0) ;
03976 if ( InnerTPCHits < MinInnerTPCHits ) return(0) ;
03977 if ( OuterTPCHits < MinOuterTPCHits ) return(0) ;
03978
03979 Int_t ChargeB, HitSector ;
03980 Float_t B[3], xx[3], xx2[3], xxprime[3] ;
03981 Double_t Xtrack[BITS], Ytrack[BITS], Ztrack[BITS] ;
03982 Double_t R[BITS], X0, Y0, X0Prime, Y0Prime, R0, Pz_over_Pt, Z_coef, DeltaTheta ;
03983 Double_t Xprime[BITS+1], Yprime[BITS+1], Zprime[BITS+1], dX[BITS+1], dY[BITS+1] ;
03984 Float_t PhiPrime, HitPhi, HitLocalPhi ;
03985 Double_t cosPhi, sinPhi, cosPhiPrime, sinPhiPrime, cosPhiMPrime, sinPhiMPrime ;
03986
03987
03988 StDetectorDbSpaceChargeR2* tempfSpaceChargeR2 = fSpaceChargeR2 ;
03989 Double_t tempSpaceChargeR2 = SpaceChargeR2 ;
03990 if (!useManualSCForPredict) ManualSpaceChargeR2(0.01,SpaceChargeEWRatio);
03991
03992 Float_t x[3] = { 0, 0, 0 } ;
03993 BField(x,B) ;
03994 ChargeB = Charge * TMath::Sign((int)1,(int)(B[2]*1000)) ;
03995 R0 = TMath::Abs( 1000.0 * Pt / ( 0.299792 * B[2] ) ) ;
03996 X0 = ChargeB * 0.0 * R0 ;
03997 Y0 = ChargeB * -1.0 * R0 ;
03998 Pz_over_Pt = TMath::SinH(PseudoRapidity) ;
03999 Z_coef = ChargeB*R0*Pz_over_Pt ;
04000
04001 PhiPrime = Phi;
04002 while ( PhiPrime < 0 ) PhiPrime += PiOver6 ;
04003 PhiPrime = fmod(PhiPrime + PiOver12,PiOver6) - PiOver12;
04004 cosPhi = TMath::Cos(Phi);
04005 sinPhi = TMath::Sin(Phi);
04006 cosPhiPrime = TMath::Cos(PhiPrime);
04007 sinPhiPrime = TMath::Sin(PhiPrime);
04008 cosPhiMPrime = cosPhi*cosPhiPrime+sinPhi*sinPhiPrime;
04009 sinPhiMPrime = sinPhi*cosPhiPrime-cosPhi*sinPhiPrime;
04010
04011 X0Prime = cosPhiPrime*X0 - sinPhiPrime*Y0;
04012 Y0Prime = sinPhiPrime*X0 + cosPhiPrime*Y0;
04013
04014
04015 R[0] = 0.0 ;
04016
04017
04018 R[1] = 6.37 ;
04019 R[2] = 7.38 ;
04020 R[3] = 10.38 ;
04021 R[4] = 11.27 ;
04022 R[5] = 14.19 ;
04023 R[6] = 15.13 ;
04024
04025
04026 R[7] = 22.8 ;
04027
04028
04029 for ( Int_t i = TPCOFFSET ; i < TPCROWS + TPCOFFSET ; i++ )
04030 {
04031 if ( (i-TPCOFFSET) < INNER8 )
04032 R[i] = 60.0 + (i-TPCOFFSET)*4.8 ;
04033 else if ( (i-TPCOFFSET) < INNER )
04034 R[i] = 93.6 + (i-TPCOFFSET-INNER8+1)*5.2 ;
04035 else
04036 R[i] = 127.195 + (i-TPCOFFSET-INNER)*2.0 ;
04037 }
04038
04039 for ( Int_t i = 0 ; i < BITS ; i++ )
04040 {
04041
04042 if ( ( i > 0 && i < 32 ) && (( RowMask1 & OneBit<<(i) ) == 0 )) continue ;
04043 if ( ( i > 0 && i >= 32 ) && (( RowMask2 & OneBit<<(i-32) ) == 0 )) continue ;
04044
04045 if ( R[i] < IFCRadius || R[i] > OFCRadius ) {
04046 Ytrack[i] = -1 * ChargeB * ( R[i]*R[i]/(2*R0) ) ;
04047 Xtrack[i] = TMath::Sqrt( R[i]*R[i] - Ytrack[i]*Ytrack[i] ) ;
04048 DeltaTheta = TMath::ATan2(-1*Y0,-1*X0) - TMath::ATan2(Ytrack[i]-Y0,Xtrack[i]-X0) ;
04049 while ( DeltaTheta < -1*TMath::Pi() ) DeltaTheta += TMath::TwoPi() ;
04050 while ( DeltaTheta >= TMath::Pi() ) DeltaTheta -= TMath::TwoPi() ;
04051 Ztrack[i] = VertexZ + DeltaTheta*Z_coef;
04052 continue ;
04053 }
04054
04055
04056
04057 Xtrack[i] = R[i] ;
04058 Ytrack[i] = ChargeB * TMath::Sqrt( R0*R0 - (Xtrack[i]-X0Prime)*(Xtrack[i]-X0Prime) ) + Y0Prime ;
04059 HitLocalPhi = TMath::ATan2(Ytrack[i],Xtrack[i]);
04060 while (TMath::Abs(HitLocalPhi) > PiOver12) {
04061
04062 PhiPrime -= TMath::Sign(PiOver6,HitLocalPhi);
04063 cosPhiPrime = TMath::Cos(PhiPrime);
04064 sinPhiPrime = TMath::Sin(PhiPrime);
04065 cosPhiMPrime = cosPhi*cosPhiPrime+sinPhi*sinPhiPrime;
04066 sinPhiMPrime = sinPhi*cosPhiPrime-cosPhi*sinPhiPrime;
04067
04068 X0Prime = cosPhiPrime*X0 - sinPhiPrime*Y0;
04069 Y0Prime = sinPhiPrime*X0 + cosPhiPrime*Y0;
04070
04071 Ytrack[i] = ChargeB * TMath::Sqrt( R0*R0 - (Xtrack[i]-X0Prime)*(Xtrack[i]-X0Prime) ) + Y0Prime ;
04072 HitLocalPhi = TMath::ATan2(Ytrack[i],Xtrack[i]);
04073 }
04074
04075 DeltaTheta = TMath::ATan2(-1*Y0Prime,-1*X0Prime) - TMath::ATan2(Ytrack[i]-Y0Prime,Xtrack[i]-X0Prime) ;
04076 while ( DeltaTheta < -1*TMath::Pi() ) DeltaTheta += TMath::TwoPi() ;
04077 while ( DeltaTheta >= TMath::Pi() ) DeltaTheta -= TMath::TwoPi() ;
04078 Ztrack[i] = VertexZ + DeltaTheta*Z_coef;
04079
04080
04081 xx2[0] = cosPhiMPrime*Xtrack[i] - sinPhiMPrime*Ytrack[i];
04082 xx2[1] = sinPhiMPrime*Xtrack[i] + cosPhiMPrime*Ytrack[i];
04083 xx2[2] = Ztrack[i];
04084
04085 xx[0] = xx2[0] ; xx[1] = xx2[1] ; xx[2] = xx2[2];
04086
04087 if (mDistortionMode & kGridLeak ||
04088 mDistortionMode & k3DGridLeak) {
04089 HitPhi = TMath::ATan2(xx[1],xx[0]) ;
04090 while ( HitPhi < 0 ) HitPhi += TMath::TwoPi() ;
04091 while ( HitPhi >= TMath::TwoPi() ) HitPhi -= TMath::TwoPi() ;
04092 HitSector = 0;
04093 SectorNumber ( HitSector, HitPhi, xx[2] );
04094 if ( GLWeights[HitSector] < 0) {
04095
04096 fSpaceChargeR2 = tempfSpaceChargeR2 ;
04097 SpaceChargeR2 = tempSpaceChargeR2 ;
04098 return(0);
04099 }
04100 }
04101
04102 if (mDistortionMode & kSpaceChargeR2) {
04103 UndoSpaceChargeR2Distortion ( xx, xxprime ) ;
04104 for ( unsigned int j = 0 ; j < 3; ++j )
04105 {
04106 xx[j] = xxprime[j];
04107 }
04108 }
04109 if (mDistortionMode & kGridLeak) {
04110 UndoGridLeakDistortion ( xx, xxprime ) ;
04111 for ( unsigned int j = 0 ; j < 3 ; ++j )
04112 {
04113 xx[j] = xxprime[j];
04114 }
04115 }
04116 if (mDistortionMode & k3DGridLeak) {
04117 Undo3DGridLeakDistortion ( xx, xxprime ) ;
04118 for ( unsigned int j = 0 ; j < 3 ; ++j )
04119 {
04120 xx[j] = xxprime[j];
04121 }
04122 }
04123
04124 xx2[0] = 2*xx2[0] - xx[0] ;
04125 xx2[1] = 2*xx2[1] - xx[1] ;
04126 xx2[2] = 2*xx2[2] - xx[2] ;
04127 Xtrack[i] = cosPhi*xx2[0] + sinPhi*xx2[1] ;
04128 Ytrack[i] = -sinPhi*xx2[0] + cosPhi*xx2[1] ;
04129 Ztrack[i] = xx2[2] ;
04130
04131 }
04132
04133 Int_t Index = -1 ;
04134 Int_t TPCIndex = -1 ;
04135 for ( Int_t i = 1 ; i < BITS ; i++ )
04136 {
04137 if ( ( i < 32 ) && (( RowMask1 & OneBit<<(i) ) == 0 )) continue ;
04138 if ( ( i >= 32 ) && (( RowMask2 & OneBit<<(i-32) ) == 0 )) continue ;
04139 Index++ ; if ( i >= TPCOFFSET ) TPCIndex++ ;
04140 Xprime[Index] = Xtrack[i] ; Yprime[Index] = Ytrack[i] ; Zprime[Index] = Ztrack[i] ;
04141 dX[Index] = RowMaskErrorR[i] ; dY[Index] = RowMaskErrorRPhi[i] ;
04142
04143 }
04144
04145 TGraphErrors gre(Index+1,Xprime,Yprime,dX,dY) ;
04146
04147
04148
04149 TF1 newDCA ("newDCA" , "( [1] + [3] * sqrt( [1]**2 - x**2 + 2*x*[0] + [2]*[2] - [2]*(2*sqrt([0]**2+[1]**2))) )" );
04150 newDCA.SetParameters( X0, Y0, 0.0, ChargeB );
04151 newDCA.FixParameter(3, ChargeB);
04152 gre.Fit("newDCA","Q") ;
04153 Double_t DCA_new = newDCA.GetParameter( 2 ) ;
04154
04155
04156 if ( DEBUG )
04157 {
04158 TCanvas* c1 = new TCanvas("A Simple Fit","The Fit", 250, 10, 700, 500) ;
04159 TCanvas* c2 = new TCanvas("The circles are OK","The circles ", 250, 800, 700, 500) ;
04160 c1 -> cd() ;
04161 gre.Draw("A*") ;
04162 c1 -> Update() ;
04163 TGraph* gra = new TGraph( Index+1, Xprime, Yprime ) ;
04164 c2 -> cd() ;
04165 gra -> SetMaximum(200) ;
04166 gra -> SetMinimum(-200) ;
04167
04168 gra -> GetXaxis() -> SetLimits(-200.,200.) ;
04169 gra -> Draw("A*") ;
04170 c2 -> Update() ;
04171 }
04172
04173 pSpace = (DCA * ChargeB) * SpaceChargeR2 / DCA_new ;
04174
04175
04176 fSpaceChargeR2 = tempfSpaceChargeR2 ;
04177 SpaceChargeR2 = tempSpaceChargeR2 ;
04178
04179 return(1) ;
04180
04181 }
04182
04183
04184
04185
04187
04188 Int_t StMagUtilities::IsPowerOfTwo(Int_t i)
04189 {
04190 Int_t j = 0;
04191 while( i > 0 ) { j += (i&1) ; i = (i>>1) ; }
04192 if ( j == 1 ) return(1) ;
04193 return(0) ;
04194 }
04195
04196
04197
04198
04200
04206 void StMagUtilities::SectorNumber( Int_t& Sector , const Float_t x[] )
04207 {
04208 if ( Sector > 0 ) return ;
04209 Float_t phi = TMath::ATan2(x[1],x[0]) ;
04210 SectorNumber( Sector, phi, x[2] ) ;
04211 }
04212 void StMagUtilities::SectorNumber( Int_t& Sector , Float_t phi, const Float_t z )
04213 {
04214 if ( Sector > 0 ) return ;
04215 if ( phi < 0 ) phi += TMath::TwoPi() ;
04216 Sector = ( ( 30 - (int)(phi/PiOver12) )%24 ) / 2 ;
04217 if ( z < 0 ) Sector = 24 - Sector ;
04218 else if ( Sector == 0 ) Sector = 12 ;
04219 }
04220
04221
04222
04223
04225
04230 Float_t StMagUtilities::LimitZ( Int_t& Sector , const Float_t x[] )
04231 {
04232 Float_t z = x[2];
04233 SectorNumber( Sector, 0, z ) ;
04234 if ( Sector <= 12 && z < 0.2 ) z = 0.2 ;
04235 else if ( Sector >= 13 && z > -0.2 ) z = -0.2 ;
04236 return z ;
04237 }
04238
04239
04240
04241
04243
04249 void StMagUtilities::UndoGridLeakDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
04250 {
04251
04252 const Int_t ORDER = 1 ;
04253 const Int_t ROWS = 513 ;
04254 const Int_t COLUMNS = 129 ;
04255 const Int_t ITERATIONS = 750 ;
04256 const Double_t GRIDSIZER = (OFCRadius-IFCRadius) / (ROWS-1) ;
04257 const Double_t GRIDSIZEZ = TPC_Z0 / (COLUMNS-1) ;
04258
04259
04260 static TMatrix EroverEz(ROWS,COLUMNS) ;
04261 static Float_t Rlist[ROWS], Zedlist[COLUMNS] ;
04262
04263 Float_t Er_integral, Ephi_integral ;
04264 Double_t r, phi, z ;
04265
04266 if ( InnerGridLeakStrength == 0 && MiddlGridLeakStrength == 0 && OuterGridLeakStrength == 0 )
04267 { Xprime[0] = x[0] ; Xprime[1] = x[1] ; Xprime[2] = x[2] ; return ; }
04268
04269 static Int_t DoOnce = 0 ;
04270
04271 if ( DoOnce == 0 )
04272 {
04273 cout << "StMagUtilities::UndoGridL Please wait for the tables to fill ... ~30 seconds" << endl ;
04274 TMatrix ArrayE(ROWS,COLUMNS), ArrayV(ROWS,COLUMNS), Charge(ROWS,COLUMNS) ;
04275
04276
04277 for ( Int_t j = 0 ; j < COLUMNS ; j++ )
04278 {
04279 Double_t zed = j*GRIDSIZEZ ;
04280 Zedlist[j] = zed ;
04281 for ( Int_t i = 0 ; i < ROWS ; i++ )
04282 {
04283 Double_t Radius = IFCRadius + i*GRIDSIZER ;
04284 ArrayV(i,j) = 0 ;
04285 Charge(i,j) = 0 ;
04286 Rlist[i] = Radius ;
04287 }
04288 }
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298 Float_t GainRatio = 3.0 ;
04299 for ( Int_t j = 1 ; j < COLUMNS-1 ; j++ )
04300 {
04301 for ( Int_t i = 1 ; i < ROWS-1 ; i++ )
04302 {
04303 Double_t Radius = IFCRadius + i*GRIDSIZER ;
04304
04305 if ( (Radius >= InnerGridLeakRadius) && (Radius < MiddlGridLeakRadius) )
04306 Charge(i,j) += InnerGridLeakStrength / (1.0e-3*Radius*Radius) ;
04307
04308 if ( (Radius >= MiddlGridLeakRadius-MiddlGridLeakWidth) && (Radius <= MiddlGridLeakRadius+MiddlGridLeakWidth) )
04309 Charge(i,j) += MiddlGridLeakStrength ;
04310
04311 if ( (Radius >= MiddlGridLeakRadius) && (Radius < OuterGridLeakRadius) )
04312 Charge(i,j) += OuterGridLeakStrength / (GainRatio*1.0e-3*Radius*Radius) ;
04313 }
04314 }
04315
04316 PoissonRelaxation( ArrayV, Charge, EroverEz, ITERATIONS ) ;
04317
04318 DoOnce = 1 ;
04319
04320 }
04321
04322 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
04323 phi = TMath::ATan2(x[1],x[0]) ;
04324 if ( phi < 0 ) phi += TMath::TwoPi() ;
04325 z = LimitZ( Sector, x ) ;
04326
04327 Float_t phi0 = PiOver6 * ((Int_t)(0.499 + phi/PiOver6)) ;
04328 Float_t local_y = r * TMath::Cos( phi - phi0 ) ;
04329
04330
04331 Er_integral = Interpolate2DTable( ORDER, local_y, TMath::Abs(z), ROWS, COLUMNS, Rlist, Zedlist, EroverEz ) ;
04332 Ephi_integral = 0.0 ;
04333
04334
04335 if (fSpaceChargeR2) GetSpaceChargeR2();
04336
04337
04338 if ( r > 0.0 )
04339 {
04340 if ( z < 0.0 )
04341 {
04342 phi = phi - SpaceChargeR2 * SpaceChargeEWRatio * ( Const_0*Ephi_integral - Const_1*Er_integral ) / r ;
04343 r = r - SpaceChargeR2 * SpaceChargeEWRatio * ( Const_0*Er_integral + Const_1*Ephi_integral ) ;
04344 }
04345 else
04346 {
04347 phi = phi - SpaceChargeR2 * ( Const_0*Ephi_integral - Const_1*Er_integral ) / r ;
04348 r = r - SpaceChargeR2 * ( Const_0*Er_integral + Const_1*Ephi_integral ) ;
04349 }
04350 }
04351
04352 Xprime[0] = r * TMath::Cos(phi) ;
04353 Xprime[1] = r * TMath::Sin(phi) ;
04354 Xprime[2] = x[2] ;
04355
04356 }
04357
04358
04359
04360
04361
04363
04367 void StMagUtilities::Undo3DGridLeakDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
04368 {
04369
04370 const Int_t ORDER = 1 ;
04371 const Int_t neR3D = 73 ;
04372 const Int_t ITERATIONS = 100 ;
04373 const Int_t SYMMETRY = 1 ;
04374 const Int_t ROWS = 513 ;
04375 const Int_t COLUMNS = 129 ;
04376 const Int_t PHISLICES = 8 ;
04377 const Float_t GRIDSIZEPHI = (2 - SYMMETRY) * TMath::Pi() / (12.0*(PHISLICES-1)) ;
04378 const Float_t GRIDSIZER = (OFCRadius-IFCRadius) / (ROWS-1) ;
04379 const Float_t GRIDSIZEZ = TPC_Z0 / (COLUMNS-1) ;
04380
04381 static TMatrix *ArrayofArrayV[PHISLICES], *ArrayofCharge[PHISLICES] ;
04382 static TMatrix *ArrayofEroverEz[PHISLICES], *ArrayofEPhioverEz[PHISLICES] ;
04383
04384 static Float_t Rlist[ROWS], Zedlist[COLUMNS] ;
04385
04386 static Int_t DoOnce = 0 ;
04387
04388 static TMatrix *ArrayoftiltEr[PHISLICES] ;
04389 static TMatrix *ArrayoftiltEphi[PHISLICES] ;
04390
04391
04392 static Float_t eRadius[neR3D] = { 50.0, 60.0, 70.0, 80.0, 90.0,
04393 100.0, 104.0, 106.5, 109.0, 111.5,
04394 114.0, 115.0, 116.0, 117.0, 118.0,
04395 118.5, 118.75, 119.0, 119.25, 119.5,
04396 119.75, 120.0, 120.25, 120.5, 120.75,
04397 121.0, 121.25, 121.5, 121.75, 122.0,
04398 122.25, 122.5, 122.75, 123.0, 123.25,
04399 123.5, 123.75, 124.0, 124.25, 124.5,
04400 124.75, 125.0, 125.25, 125.5, 126.0,
04401 126.25, 126.5, 126.75, 127.0, 127.25,
04402 127.5, 128.0, 128.5, 129.0, 129.5,
04403 130.0, 130.5, 131.0, 131.5, 132.0,
04404 133.0, 135.0, 137.5, 140.0, 145.0,
04405 150.0, 160.0, 170.0, 180.0, 190.0,
04406 195.0, 198.0, 200.0 } ;
04407
04408 static Float_t Philist[PHISLICES] ;
04409
04410 for ( Int_t k = 0 ; k < PHISLICES ; k++ ) Philist[k] = GRIDSIZEPHI * k ;
04411
04412 Float_t Er_integral, Ephi_integral ;
04413 Float_t r, phi, z ;
04414
04415 Xprime[0] = x[0] ;
04416 Xprime[1] = x[1] ;
04417 Xprime[2] = x[2] ;
04418
04419 if ( MiddlGridLeakStrength == 0 ) return ;
04420
04421 if ( DoOnce == 0 )
04422 {
04423 cout << "StMagUtilities::Undo3DGrid Please wait for the tables to fill ... ~5 seconds * PHISLICES" << endl ;
04424
04425 for ( Int_t k = 0 ; k < PHISLICES ; k++ )
04426 {
04427 ArrayoftiltEr[k] = new TMatrix(neR3D,EMap_nZ) ;
04428 ArrayoftiltEphi[k] = new TMatrix(neR3D,EMap_nZ) ;
04429 }
04430
04431 for ( Int_t k = 0 ; k < PHISLICES ; k++ )
04432 {
04433 ArrayofArrayV[k] = new TMatrix(ROWS,COLUMNS) ;
04434 ArrayofCharge[k] = new TMatrix(ROWS,COLUMNS) ;
04435 ArrayofEroverEz[k] = new TMatrix(ROWS,COLUMNS) ;
04436 ArrayofEPhioverEz[k] = new TMatrix(ROWS,COLUMNS) ;
04437 }
04438
04439 for ( Int_t k = 0 ; k < PHISLICES ; k++ )
04440 {
04441 TMatrix &ArrayV = *ArrayofArrayV[k] ;
04442 TMatrix &Charge = *ArrayofCharge[k] ;
04443
04444
04445 for ( Int_t i = 0 ; i < ROWS ; i++ )
04446 {
04447 Rlist[i] = IFCRadius + i*GRIDSIZER ;
04448 for ( Int_t j = 0 ; j < COLUMNS ; j++ )
04449 {
04450 Zedlist[j] = j * GRIDSIZEZ ;
04451 ArrayV(i,j) = 0.0 ;
04452 Charge(i,j) = 0.0 ;
04453 }
04454 }
04455
04456 for ( Int_t i = 1 ; i < ROWS-1 ; i++ )
04457 {
04458 Float_t Radius = IFCRadius + i*GRIDSIZER ;
04459 for ( Int_t j = 1 ; j < COLUMNS-1 ; j++ )
04460 {
04461
04462 Float_t top = 0, bottom = 0 ;
04463
04464 Float_t local_y_hi = (Radius+GRIDSIZER/2.0) * TMath::Cos(Philist[k]) ;
04465 Float_t local_y_lo = (Radius-GRIDSIZER/2.0) * TMath::Cos(Philist[k]) ;
04466 Float_t charge_y_hi = GAPRADIUS + GAP13_14/2.0 ;
04467 Float_t charge_y_lo = GAPRADIUS - GAP13_14/2.0 ;
04468
04469 if (local_y_hi > charge_y_lo && local_y_hi < charge_y_hi)
04470 {
04471 top = local_y_hi ;
04472 if (local_y_lo > charge_y_lo && local_y_lo < charge_y_hi)
04473 bottom = local_y_lo ;
04474 else
04475 bottom = charge_y_lo ;
04476 }
04477
04478 if (local_y_lo > charge_y_lo && local_y_lo < charge_y_hi)
04479 {
04480 bottom = local_y_lo ;
04481 if (local_y_hi > charge_y_lo && local_y_hi < charge_y_hi)
04482 top = local_y_hi ;
04483 else
04484 top = charge_y_hi ;
04485 }
04486
04487 Float_t Weight = 1. / (local_y_hi*local_y_hi - local_y_lo*local_y_lo) ;
04488
04489
04490 const Float_t BackwardsCompatibilityRatio = 3.75 ;
04491 Charge(i,j) = (top*top-bottom*bottom) * Weight * MiddlGridLeakStrength*BackwardsCompatibilityRatio ;
04492
04493 }
04494 }
04495 }
04496
04497
04498
04499
04500 Poisson3DRelaxation( ArrayofArrayV, ArrayofCharge, ArrayofEroverEz, ArrayofEPhioverEz, PHISLICES,
04501 GRIDSIZEPHI, ITERATIONS, SYMMETRY) ;
04502
04503
04504
04505 for ( Int_t k = 0 ; k < PHISLICES ; k++ )
04506 {
04507 TMatrix &tiltEr = *ArrayoftiltEr[k] ;
04508 TMatrix &tiltEphi = *ArrayoftiltEphi[k] ;
04509 phi = Philist[k] ;
04510 for ( Int_t i = 0 ; i < EMap_nZ ; i++ )
04511 {
04512 z = TMath::Abs(eZList[i]) ;
04513 for ( Int_t j = 0 ; j < neR3D ; j++ )
04514 {
04515 r = eRadius[j] ;
04516 tiltEr(j,i) = Interpolate3DTable( ORDER,r,z,phi,ROWS,COLUMNS,PHISLICES,Rlist,Zedlist,Philist,ArrayofEroverEz ) ;
04517 tiltEphi(j,i) = Interpolate3DTable( ORDER,r,z,phi,ROWS,COLUMNS,PHISLICES,Rlist,Zedlist,Philist,ArrayofEPhioverEz ) ;
04518 }
04519 }
04520 }
04521
04522 for ( Int_t k = 0 ; k < PHISLICES ; k++ )
04523 {
04524 ArrayofArrayV[k] -> Delete() ;
04525 ArrayofCharge[k] -> Delete() ;
04526 ArrayofEroverEz[k] -> Delete() ;
04527 ArrayofEPhioverEz[k] -> Delete() ;
04528 }
04529
04530 DoOnce = 1 ;
04531
04532 }
04533
04534 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
04535 phi = TMath::ATan2(x[1],x[0]) ;
04536 if ( phi < 0 ) phi += TMath::TwoPi() ;
04537 z = LimitZ( Sector, x ) ;
04538
04539 Float_t phi_prime, local_y, r_eff, FLIP = 1.0 ;
04540 phi_prime = phi ;
04541 if ( SYMMETRY == 1 )
04542 {
04543 Int_t N = (int)(phi/PiOver12) ;
04544 phi_prime = phi - N * PiOver12 ;
04545 if ( TMath::Power(-1,N) < 0 ) phi_prime = PiOver12 - phi_prime ;
04546 if ( TMath::Power(-1,N) < 0 ) FLIP = -1 ;
04547 }
04548
04549 r_eff = r ;
04550 local_y = r * TMath::Cos(phi_prime) ;
04551 if ( local_y > GAPRADIUS - GAP13_14 && local_y < GAPRADIUS ) r_eff = (GAPRADIUS - GAP13_14) / TMath::Cos(phi_prime) ;
04552 if ( local_y < GAPRADIUS + GAP13_14 && local_y > GAPRADIUS ) r_eff = (GAPRADIUS + GAP13_14) / TMath::Cos(phi_prime) ;
04553
04554
04555 Er_integral = Interpolate3DTable( ORDER, r_eff, TMath::Abs(z), phi_prime, neR3D, EMap_nZ, PHISLICES, eRadius, eZList, Philist, ArrayoftiltEr ) ;
04556 Ephi_integral = Interpolate3DTable( ORDER, r_eff, TMath::Abs(z), phi_prime, neR3D, EMap_nZ, PHISLICES, eRadius, eZList, Philist, ArrayoftiltEphi ) ;
04557 Ephi_integral *= FLIP ;
04558
04559 if (fSpaceChargeR2) GetSpaceChargeR2();
04560
04561
04562
04563 if ( r > 0.0 )
04564 {
04565 Float_t Weight = SpaceChargeR2 * (GLWeights[Sector] >= 0 ? GLWeights[Sector] : 1) ;
04566 if ( z < 0.0 ) Weight *= SpaceChargeEWRatio ;
04567 phi = phi - Weight * ( Const_0*Ephi_integral - Const_1*Er_integral ) / r ;
04568 r = r - Weight * SpaceChargeEWRatio * ( Const_0*Er_integral + Const_1*Ephi_integral ) ;
04569 }
04570
04571 Xprime[0] = r * TMath::Cos(phi) ;
04572 Xprime[1] = r * TMath::Sin(phi) ;
04573 Xprime[2] = x[2] ;
04574
04575 }
04576
04577
04578
04579
04581
04591 void StMagUtilities::UndoSectorAlignDistortion( const Float_t x[], Float_t Xprime[] , Int_t Sector )
04592 {
04593
04594 const Int_t ORDER = 1 ;
04595 const Int_t neR3D = 73 ;
04596 const Int_t ITERATIONS = 100 ;
04597 const Int_t ROWS = 257 ;
04598 const Int_t COLUMNS = 65 ;
04599 const Int_t PHISLICES = 180 ;
04600
04601 const Int_t PHISLICES1 = PHISLICES+1 ;
04602 const Float_t GRIDSIZEPHI = TMath::TwoPi() / PHISLICES ;
04603 const Float_t GRIDSIZER = (OFCRadius-IFCRadius) / (ROWS-1) ;
04604 const Float_t GRIDSIZEZ = TPC_Z0 / (COLUMNS-1) ;
04605
04606 const Float_t INNERGGSpan = 68.0 ;
04607 const Float_t OUTERGGSpan = 68.8 ;
04608 const Float_t INNERGGFirst = 53.0 ;
04609 const Float_t INNERGGLast = INNERGGFirst + INNERGGSpan ;
04610 const Float_t OUTERGGFirst = INNERGGLast + GAP13_14 ;
04611 const Float_t OUTERGGLast = OUTERGGFirst + OUTERGGSpan ;
04612
04613 static TMatrix *ArrayofArrayV[PHISLICES] , *ArrayofCharge[PHISLICES] ;
04614 static TMatrix *ArrayofEroverEzW[PHISLICES], *ArrayofEPhioverEzW[PHISLICES] ;
04615 static TMatrix *ArrayofEroverEzE[PHISLICES], *ArrayofEPhioverEzE[PHISLICES] ;
04616
04617 static Float_t Rlist[ROWS], Zedlist[COLUMNS] ;
04618
04619 static Int_t DoOnce = 0 ;
04620
04621 static TMatrix *ArrayoftiltEr[PHISLICES1] ;
04622 static TMatrix *ArrayoftiltEphi[PHISLICES1] ;
04623
04624
04625 static Float_t eRadius[neR3D] = { 50.0, 60.0, 70.0, 80.0, 90.0,
04626 100.0, 104.0, 106.5, 109.0, 111.5,
04627 114.0, 115.0, 116.0, 117.0, 118.0,
04628 118.5, 118.75, 119.0, 119.25, 119.5,
04629 119.75, 120.0, 120.25, 120.5, 120.75,
04630 121.0, 121.25, 121.5, 121.75, 122.0,
04631 122.25, 122.5, 122.75, 123.0, 123.25,
04632 123.5, 123.75, 124.0, 124.25, 124.5,
04633 124.75, 125.0, 125.25, 125.5, 126.0,
04634 126.25, 126.5, 126.75, 127.0, 127.25,
04635 127.5, 128.0, 128.5, 129.0, 129.5,
04636 130.0, 130.5, 131.0, 131.5, 132.0,
04637 133.0, 135.0, 137.5, 140.0, 145.0,
04638 150.0, 160.0, 170.0, 180.0, 190.0,
04639 195.0, 198.0, 200.0 } ;
04640
04641 static Float_t Philist [PHISLICES1] ;
04642
04643 Float_t Er_integral, Ephi_integral ;
04644 Float_t r, phi, z ;
04645
04646
04647
04648 Xprime[0] = x[0] ;
04649 Xprime[1] = x[1] ;
04650 Xprime[2] = x[2] ;
04651
04652 if ( DoOnce == 0 )
04653 {
04654 cout << "StMagUtilities::UndoSectorAlign Please wait for the tables to fill ... ~5 seconds * PHISLICES" << endl ;
04655 Int_t SeclistW[PHISLICES1] ;
04656 Int_t SeclistE[PHISLICES1] ;
04657 Float_t SecPhis [PHISLICES1] ;
04658
04659 for ( Int_t k = 0 ; k < PHISLICES1 ; k++ )
04660 {
04661 Philist[k] = GRIDSIZEPHI * k ;
04662 Int_t k2 = (12*k+PHISLICES/2)/PHISLICES;
04663 SeclistW[k] = (14-k2)%12+1;
04664 SeclistE[k] = (k2+8)%12+13;
04665 SecPhis[k] = GRIDSIZEPHI * (k2*PHISLICES/12-k) ;
04666 }
04667
04668 for ( Int_t k = 0 ; k < PHISLICES1 ; k++ )
04669 {
04670 ArrayoftiltEr[k] = new TMatrix(neR3D,EMap_nZ) ;
04671 ArrayoftiltEphi[k] = new TMatrix(neR3D,EMap_nZ) ;
04672 }
04673
04674 for ( Int_t k = 0 ; k < PHISLICES ; k++ )
04675 {
04676 ArrayofArrayV[k] = new TMatrix(ROWS,COLUMNS) ;
04677 ArrayofCharge[k] = new TMatrix(ROWS,COLUMNS) ;
04678 ArrayofEroverEzW[k] = new TMatrix(ROWS,COLUMNS) ;
04679 ArrayofEPhioverEzW[k] = new TMatrix(ROWS,COLUMNS) ;
04680 ArrayofEroverEzE[k] = new TMatrix(ROWS,COLUMNS) ;
04681 ArrayofEPhioverEzE[k] = new TMatrix(ROWS,COLUMNS) ;
04682 }
04683
04684 for ( Int_t m = -1; m < 2 ; m+=2 )
04685 {
04686 TMatrix** ArrayofEroverEz = ( m < 0 ? ArrayofEroverEzW : ArrayofEroverEzE ) ;
04687 TMatrix** ArrayofEPhioverEz = ( m < 0 ? ArrayofEPhioverEzW : ArrayofEPhioverEzE ) ;
04688 Int_t* Seclist = ( m < 0 ? SeclistW : SeclistE ) ;
04689
04690
04691 for ( Int_t k = 0 ; k < PHISLICES ; k++ )
04692 {
04693 TMatrix &ArrayV = *ArrayofArrayV[k] ;
04694 TMatrix &Charge = *ArrayofCharge[k] ;
04695
04696
04697 for ( Int_t i = 0 ; i < ROWS ; i++ )
04698 {
04699 Rlist[i] = IFCRadius + i*GRIDSIZER ;
04700 for ( Int_t j = 0 ; j < COLUMNS ; j++ )
04701 {
04702 Zedlist[j] = j * GRIDSIZEZ ;
04703 ArrayV(i,j) = 0.0 ;
04704 Charge(i,j) = 0.0 ;
04705 }
04706 }
04707
04708 Double_t tanSecPhi = TMath::Tan(SecPhis[k]);
04709 Double_t cosSecPhi = TMath::Cos(SecPhis[k]);
04710 Double_t secSecPhi = 1.0/cosSecPhi;
04711 Double_t iOffsetFirst, iOffsetLast, oOffsetFirst, oOffsetLast;
04712
04713 if (thedb)
04714 {
04715
04716 Double_t local[3] = {0,0,0};
04717 Double_t master[3];
04718
04719
04720
04721
04722
04723
04724
04725 const TGeoHMatrix& iAlignMatrix = thedb->SubSInner2Tpc(Seclist[k]);
04726 const TGeoHMatrix& oAlignMatrix = thedb->SubSOuter2Tpc(Seclist[k]);
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736
04737
04738
04739
04740
04741 local[0] = m * INNERGGFirst * tanSecPhi;
04742 local[1] = INNERGGFirst;
04743 iAlignMatrix.LocalToMaster(local,master);
04744 iOffsetFirst = (TPC_Z0 + m * master[2]) * StarMagE;
04745
04746 local[0] = m * INNERGGLast * tanSecPhi;
04747 local[1] = INNERGGLast;
04748 iAlignMatrix.LocalToMaster(local,master);
04749 iOffsetLast = (TPC_Z0 + m * master[2]) * StarMagE;
04750
04751 local[0] = m * OUTERGGFirst * tanSecPhi;
04752 local[1] = OUTERGGFirst;
04753 oAlignMatrix.LocalToMaster(local,master);
04754 oOffsetFirst = (TPC_Z0 + m * master[2]) * StarMagE;
04755
04756 local[0] = m * OUTERGGLast * tanSecPhi;
04757 local[1] = OUTERGGLast;
04758 oAlignMatrix.LocalToMaster(local,master);
04759 oOffsetLast = (TPC_Z0 + m * master[2]) * StarMagE;
04760
04761 } else {
04762
04763
04764
04765 iOffsetFirst = 0;
04766 iOffsetLast = 0;
04767 oOffsetFirst = (Seclist[k] == 12 || Seclist[k] == 24 ?
04768 0.1 * StarMagE * (1.5 - Seclist[k]/24.) : 0);
04769 oOffsetLast = 0;
04770
04771 }
04772
04773
04774
04775 for ( Int_t i = 1 ; i < ROWS-1 ; i++ )
04776 {
04777 Double_t Radius = IFCRadius + i*GRIDSIZER ;
04778 Double_t local_y = Radius * cosSecPhi ;
04779 Double_t tempV;
04780 if (local_y <= INNERGGFirst)
04781 tempV = iOffsetFirst*(Radius - IFCRadius)/(INNERGGFirst*secSecPhi - IFCRadius);
04782 else if (local_y <= INNERGGLast)
04783 tempV = iOffsetFirst + (iOffsetLast -iOffsetFirst)*(local_y-INNERGGFirst)/INNERGGSpan;
04784 else if (local_y <= OUTERGGFirst)
04785 tempV = iOffsetLast + (oOffsetFirst-iOffsetLast) *(local_y-INNERGGLast) /GAP13_14;
04786 else if (local_y <= OUTERGGLast)
04787 tempV = oOffsetFirst + (oOffsetLast -oOffsetFirst)*(local_y-OUTERGGFirst)/OUTERGGSpan;
04788 else
04789 tempV = oOffsetLast*(OFCRadius - Radius)/(OFCRadius - OUTERGGLast*secSecPhi);
04790 ArrayV(i,COLUMNS-1) = tempV;
04791 }
04792 }
04793
04794
04795
04796
04797 Poisson3DRelaxation( ArrayofArrayV, ArrayofCharge, ArrayofEroverEz, ArrayofEPhioverEz, PHISLICES,
04798 GRIDSIZEPHI, ITERATIONS, 0) ;
04799 }
04800
04801
04802
04803
04804 for ( Int_t k = 0 ; k < PHISLICES1 ; k++ )
04805 {
04806 TMatrix &tiltEr = *ArrayoftiltEr[k] ;
04807 TMatrix &tiltEphi = *ArrayoftiltEphi[k] ;
04808 phi = Philist[k == PHISLICES ? 0 : k] ;
04809 for ( Int_t i = 0 ; i < EMap_nZ ; i++ )
04810 {
04811 z = TMath::Abs(eZList[i]) ;
04812 TMatrix** ArrayofEroverEz = ( eZList[i] > 0 ? ArrayofEroverEzW : ArrayofEroverEzE ) ;
04813 TMatrix** ArrayofEPhioverEz = ( eZList[i] > 0 ? ArrayofEPhioverEzW : ArrayofEPhioverEzE ) ;
04814 for ( Int_t j = 0 ; j < neR3D ; j++ )
04815 {
04816 r = eRadius[j] ;
04817 tiltEr(j,i) = Interpolate3DTable( ORDER,r,z,phi,ROWS,COLUMNS,PHISLICES,Rlist,Zedlist,Philist,ArrayofEroverEz ) ;
04818 tiltEphi(j,i) = Interpolate3DTable( ORDER,r,z,phi,ROWS,COLUMNS,PHISLICES,Rlist,Zedlist,Philist,ArrayofEPhioverEz ) ;
04819 }
04820 }
04821 }
04822
04823 for ( Int_t k = 0 ; k < PHISLICES ; k++ )
04824 {
04825 ArrayofArrayV[k] -> Delete() ;
04826 ArrayofCharge[k] -> Delete() ;
04827 ArrayofEroverEzW[k] -> Delete() ;
04828 ArrayofEPhioverEzW[k] -> Delete() ;
04829 ArrayofEroverEzE[k] -> Delete() ;
04830 ArrayofEPhioverEzE[k] -> Delete() ;
04831 }
04832
04833 DoOnce = 1 ;
04834
04835 }
04836
04837 r = TMath::Sqrt( x[0]*x[0] + x[1]*x[1] ) ;
04838 phi = TMath::ATan2(x[1],x[0]) ;
04839 if ( phi < 0 ) phi += TMath::TwoPi() ;
04840 z = LimitZ( Sector, x ) ;
04841
04842
04843 Er_integral = Interpolate3DTable( ORDER, r, z, phi, neR3D, EMap_nZ, PHISLICES1, eRadius, eZList, Philist, ArrayoftiltEr ) ;
04844 Ephi_integral = Interpolate3DTable( ORDER, r, z, phi, neR3D, EMap_nZ, PHISLICES1, eRadius, eZList, Philist, ArrayoftiltEphi ) ;
04845
04846 if ( r > 0.0 )
04847 {
04848 phi = phi - ( Const_0*Ephi_integral - Const_1*Er_integral ) / r ;
04849 r = r - ( Const_0*Er_integral + Const_1*Ephi_integral ) ;
04850 }
04851
04852 Xprime[0] = r * TMath::Cos(phi) ;
04853 Xprime[1] = r * TMath::Sin(phi) ;
04854 Xprime[2] = x[2] ;
04855
04856 }
04857
04858
04859