00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <assert.h>
00014 #include "StTpcRSMaker.h"
00015 #include "Stiostream.h"
00016
00017 #include "StGlobals.hh"
00018 #include "StThreeVectorD.hh"
00019 #include "StPhysicalHelixD.hh"
00020
00021 #include "TClassTable.h"
00022 #include "TDataSetIter.h"
00023 #include "TTableSorter.h"
00024 #include "TRandom.h"
00025 #include "TSystem.h"
00026 #include "TFile.h"
00027 #include "TBenchmark.h"
00028 #include "TProfile2D.h"
00029 #include "TVirtualMC.h"
00030 #include "TInterpreter.h"
00031 #include "Math/SpecFuncMathMore.h"
00032
00033 #include "StDbUtilities/StTpcCoordinateTransform.hh"
00034 #include "StDbUtilities/StCoordinates.hh"
00035 #include "StDbUtilities/StMagUtilities.h"
00036 #include "StDaqLib/TPC/trans_table.hh"
00037 #include "StDetectorDbMaker/St_tpcAltroParamsC.h"
00038 #include "StDetectorDbMaker/St_asic_thresholdsC.h"
00039 #include "StDetectorDbMaker/St_tss_tssparC.h"
00040 #include "StDetectorDbMaker/St_tpcPadGainT0C.h"
00041 #include "StDetectorDbMaker/St_TpcResponseSimulatorC.h"
00042 #include "StDetectorDbMaker/St_tpcAnodeHVavgC.h"
00043 #include "StDetectorDbMaker/StDetectorDbTpcRDOMasks.h"
00044 #include "StDetectorDbMaker/St_tpcPadPlanesC.h"
00045 #include "StParticleTable.hh"
00046 #include "StParticleDefinition.hh"
00047 #include "Altro.h"
00048 #include "TRVector.h"
00049 #include "StBichsel/Bichsel.h"
00050
00051 #if defined(__DEBUG__)
00052 #define PrPP(A,B) if (Debug()%10 > 2) {LOG_INFO << "StTpcRSMaker::" << (#A) << "\t" << (#B) << " = \t" << (B) << endm;}
00053 #else
00054 #define PrPP(A,B)
00055 #endif
00056 static const char rcsid[] = "$Id: StTpcRSMaker.cxx,v 1.59 2012/05/07 15:36:22 fisyak Exp $";
00057
00058 #define Laserino 170
00059 #define Chasrino 171
00060 #define __PAD_BLOCK__
00061
00062 static Double_t t0IO[2] = {1.20868e-9, 1.43615e-9};
00063 static const Double_t tauC[2] = {999.655e-9, 919.183e-9};
00064 TF1F* StTpcRSMaker::fgTimeShape3[2] = {0, 0};
00065 TF1F* StTpcRSMaker::fgTimeShape0[2] = {0, 0};
00066
00067 static const Int_t nx[2] = {200,500};
00068 static const Double_t xmin[2] = {-10., -6};
00069 static const Double_t xmax[2] = { 10., 44};
00070 #ifdef __ClusterProfile__
00071 static const Int_t nz = 42;
00072 static const Double_t zmin = -210;
00073 static const Double_t zmax = -zmin;
00074
00075 static TProfile2D *hist[4][2];
00076 static const Int_t nChecks = 19;
00077 static TH1 *checkList[2][19];
00078 #endif
00079
00080 ClassImp(StTpcRSMaker);
00081
00082 StTpcRSMaker::StTpcRSMaker(const char *name):
00083 StMaker(name),
00084 mLaserScale(1),
00085 minSignal(1e-4),
00086 innerSectorAnodeVoltage(1170),
00087 outerSectorAnodeVoltage(1390),
00088 ElectronRange(0.0055),
00089 ElectronRangeEnergy(3000),
00090 ElectronRangePower(1.78),
00091 NoOfSectors(24),
00092 NoOfRows(-1),
00093 NoOfInnerRows(-1),
00094 NoOfPads(182),
00095 NoOfTimeBins(__MaxNumberOfTimeBins__),
00096 mCutEle(1e-4)
00097 {
00098 memset(beg, 0, end-beg+1);
00099 m_Mode = 0;
00100
00101 SETBIT(m_Mode,kBICHSEL);
00102 SETBIT(m_Mode,kdEdxCorr);
00103 SETBIT(m_Mode,kDistortion);
00104 }
00105
00106 StTpcRSMaker::~StTpcRSMaker() {
00107 SafeDelete(mAltro);
00108 Finish();
00109 }
00110
00111 Int_t StTpcRSMaker::Finish() {
00112
00113 free(m_SignalSum); m_SignalSum = 0;
00114 SafeDelete(mdNdx);
00115 SafeDelete(mdNdE);
00116 for (Int_t io = 0; io < 2; io++) {
00117 for (Int_t sec = 0; sec < NoOfSectors; sec++) {
00118 if (mShaperResponses[io][sec] && !mShaperResponses[io][sec]->TestBit(kNotDeleted)) {SafeDelete(mShaperResponses[io][sec]);}
00119 }
00120 SafeDelete(mChargeFraction[io]);
00121 SafeDelete(mPadResponseFunction[io]);
00122 SafeDelete(mChargeFraction[io]);
00123 SafeDelete(mPadResponseFunction[io]);
00124 SafeDelete(mPolya[io]);
00125 }
00126 SafeDelete(m_TpcdEdxCorrection);
00127 SafeDelete(mPAI);
00128 return StMaker::Finish();
00129 }
00130
00131 Int_t StTpcRSMaker::InitRun(Int_t ) {
00132 if (!gStTpcDb) {
00133 LOG_ERROR << "Database Missing! Can't initialize TpcRS" << endm;
00134 return kStFatal;
00135 }
00136 NoOfInnerRows = St_tpcPadPlanesC::instance()->innerPadRows();
00137 NoOfRows = NoOfInnerRows + St_tpcPadPlanesC::instance()->outerPadRows();
00138 #if 0
00139 if (! gMC) {
00140 LOG_INFO << "TVirtualMC has not been instantiated" << endm;
00141 return kStFatal;
00142 }
00143 TString cmd("Gccuts_t *ccuts = (Gccuts_t *) ((");
00144 if (gClassTable->GetID("TGiant3") >= 0) {
00145 cmd += "TGiant";
00146 } else {
00147 cmd += "TGeant";
00148 }
00149 cmd += Form(" *) %p))->Gccuts();",gMC);
00150 cmd += Form("((StTpcRSMaker *) %p)->SetCutEle(ccuts->cutele);",this);
00151 TInterpreter::EErrorCode error = TInterpreter::kNoError;
00152 gInterpreter->ProcessLine(cmd.Data(), &error);
00153 assert(error == TInterpreter::kNoError);
00154 #endif
00155 if (TESTBIT(m_Mode, kPAI)) {
00156 mPAI = PAI::Instance();
00157 LOG_INFO << "StTpcRSMaker:: use PAI model for dE/dx simulation" << endm;
00158 }
00159 else if (TESTBIT(m_Mode, kBICHSEL)) {
00160 LOG_INFO << "StTpcRSMaker:: use H.Bichsel model for dE/dx simulation" << endm;
00161 if (! mdNdE || ! mdNdx) {
00162 const Char_t *path = ".:./StarDb/dEdxModel:./StarDb/global/dEdx"
00163 ":./StRoot/StBichsel:$STAR/StarDb/dEdxModel:$STAR/StarDb/global/dEdx:$STAR/StRoot/StBichsel";
00164 const Char_t *Files[2] = {"dNdE_Bichsel.root","dNdx_Bichsel.root"};
00165 for (Int_t i = 0; i < 2; i++) {
00166 Char_t *file = gSystem->Which(path,Files[i],kReadPermission);
00167 if (! file) Fatal("StTpcRSMaker::Init","File %s has not been found in path %s",Files[i],path);
00168 else Warning("StTpcRSMaker::Init","File %s has been found as %s",Files[i],file);
00169 TFile *pFile = new TFile(file);
00170 if (i == 0) {mdNdE = (TH1D *) pFile->Get("dNdELnr"); assert(mdNdE); mdNdE->SetDirectory(0);}
00171 if (i == 1) {mdNdx = (TH1D *) pFile->Get("dNdx"); assert(mdNdx); mdNdx->SetDirectory(0);}
00172 delete pFile;
00173 }
00174 }
00175 }
00176 else {LOG_INFO << "StTpcRSMaker:: use GEANT321 model for dE/dx simulation" << endm;}
00177
00178 if (TESTBIT(m_Mode,kdEdxCorr)) {
00179 LOG_INFO << "StTpcRSMaker:: use Tpc dE/dx correction from calibaration" << endm;
00180 Int_t Mask = -1;
00181 CLRBIT(Mask,StTpcdEdxCorrection::kAdcCorrection);
00182 CLRBIT(Mask,StTpcdEdxCorrection::kdXCorrection);
00183 m_TpcdEdxCorrection = new StTpcdEdxCorrection(Mask, Debug());
00184 }
00185 if (TESTBIT(m_Mode,kDistortion)) {
00186 LOG_INFO << "StTpcRSMaker:: use Tpc distortion correction" << endm;
00187 }
00188 if (Debug() && gStTpcDb->PadResponse()) gStTpcDb->PadResponse()->Table()->Print(0,1);
00189 Double_t samplingFrequency = 1.e6*gStTpcDb->Electronics()->samplingFrequency();
00190 Double_t TimeBinWidth = 1./samplingFrequency;
00191 numberOfInnerSectorAnodeWires = gStTpcDb->WirePlaneGeometry()->numberOfInnerSectorAnodeWires ();
00192 firstInnerSectorAnodeWire = gStTpcDb->WirePlaneGeometry()->firstInnerSectorAnodeWire();
00193 lastInnerSectorAnodeWire = gStTpcDb->WirePlaneGeometry()->lastInnerSectorAnodeWire ();
00194 numberOfOuterSectorAnodeWires = gStTpcDb->WirePlaneGeometry()->numberOfOuterSectorAnodeWires ();
00195 firstOuterSectorAnodeWire = gStTpcDb->WirePlaneGeometry()->firstOuterSectorAnodeWire();
00196 lastOuterSectorAnodeWire = gStTpcDb->WirePlaneGeometry()->lastOuterSectorAnodeWire ();
00197 anodeWirePitch = gStTpcDb->WirePlaneGeometry()->anodeWirePitch ();
00198 anodeWireRadius = gStTpcDb->WirePlaneGeometry()->anodeWireRadius();
00199 Float_t BFieldG[3];
00200 Float_t xyz[3] = {0,0,0};
00201 StMagF::Agufld(xyz,BFieldG);
00202
00203 Double_t timeBinMin = -0.5;
00204 Double_t timeBinMax = 44.5;
00205 const Char_t *Names[2] = {"I","O"};
00206 Double_t CathodeAnodeGap[2] = {0.2, 0.4};
00207 innerSectorAnodeVoltage = outerSectorAnodeVoltage = 0;
00208 Int_t nAliveInner = 0;
00209 Int_t nAliveOuter = 0;
00210 for (Int_t sec = 1; sec <= 24; sec++) {
00211 for (Int_t row = 1; row <= NoOfRows; row++) {
00212 if (St_tpcAnodeHVavgC::instance()->livePadrow(sec,row)) {
00213 if (row <= NoOfInnerRows) {
00214 nAliveInner++;
00215 innerSectorAnodeVoltage += St_tpcAnodeHVavgC::instance()->voltagePadrow(sec,row);
00216 } else {
00217 nAliveOuter++;
00218 outerSectorAnodeVoltage += St_tpcAnodeHVavgC::instance()->voltagePadrow(sec,row);
00219 }
00220 }
00221 }
00222 }
00223 if (! nAliveInner && ! nAliveOuter) {
00224 LOG_INFO << "Illegal date/time. Tpc Anode Voltage is not set to run condition: AliveInner: " << nAliveInner
00225 << "\tAliveOuter: " << nAliveOuter
00226 << "\tStop the run" << endm;
00227 assert(nAliveInner || nAliveOuter);
00228 }
00229 if (nAliveInner > 1) innerSectorAnodeVoltage /= nAliveInner;
00230 if (nAliveOuter > 1) outerSectorAnodeVoltage /= nAliveOuter;
00231
00232 for (Int_t io = 0; io < 2; io++) {
00233 if (io == 0) {
00234 LOG_INFO << "Inner Sector ======================" << endm;
00235 InnerAlphaVariation = InducedCharge(anodeWirePitch,
00236 CathodeAnodeGap[io],
00237 anodeWireRadius,
00238 innerSectorAnodeVoltage, t0IO[io]);
00239 }
00240 else {
00241 LOG_INFO << "Outer Sector ======================" << endm;
00242 OuterAlphaVariation = InducedCharge(anodeWirePitch,
00243 CathodeAnodeGap[io],
00244 anodeWireRadius,
00245 outerSectorAnodeVoltage, t0IO[io]);
00246 }
00247 Double_t params3[7] = {t0IO[io],
00248 St_TpcResponseSimulatorC::instance()->tauF(),
00249 St_TpcResponseSimulatorC::instance()->tauP(),
00250 St_TpcResponseSimulatorC::instance()->tauIntegration(),
00251 TimeBinWidth, 0, io};
00252 Double_t params0[5] = {t0IO[io], St_TpcResponseSimulatorC::instance()->tauX()[io], TimeBinWidth, 0, io};
00253 if (! fgTimeShape3[io]) {
00254 fgTimeShape3[io] = new TF1F(Form("TimeShape3%s",Names[io]),
00255 shapeEI3,timeBinMin*TimeBinWidth,timeBinMax*TimeBinWidth,7);
00256 fgTimeShape3[io]->SetParNames("t0","tauF","tauP", "tauI","width","tauC","io");
00257 fgTimeShape3[io]->SetParameters(params3);
00258 params3[5] = fgTimeShape3[io]->Integral(timeBinMin*TimeBinWidth,timeBinMax*TimeBinWidth);
00259 fgTimeShape3[io]->SetTitle(fgTimeShape3[io]->GetName());
00260 fgTimeShape3[io]->GetXaxis()->SetTitle("time (secs)");
00261 fgTimeShape3[io]->GetYaxis()->SetTitle("signal");
00262 }
00263 if (! fgTimeShape0[io]) {
00264 fgTimeShape0[io] = new TF1F(Form("TimeShape%s",Names[io]),
00265 shapeEI,timeBinMin*TimeBinWidth,timeBinMax*TimeBinWidth,5);
00266 fgTimeShape0[io]->SetParNames("t0","tauI","width","tauC","io");
00267 params0[3] = St_TpcResponseSimulatorC::instance()->tauC()[io];
00268 fgTimeShape0[io]->SetParameters(params0);
00269 params0[3] = fgTimeShape0[io]->Integral(0,timeBinMax*TimeBinWidth);
00270 fgTimeShape0[io]->SetTitle(fgTimeShape0[io]->GetName());
00271 fgTimeShape0[io]->GetXaxis()->SetTitle("time (secs)");
00272 fgTimeShape0[io]->GetYaxis()->SetTitle("signal");
00273 }
00274
00275 for (Int_t sector = 1; sector <= NoOfSectors; sector++) {
00276 if (St_tpcAltroParamsC::instance()->N(sector-1) < 0) {
00277
00278 for (Int_t sec = 1; sec < sector; sec++) {
00279 if (St_tpcAltroParamsC::instance()->N(sec-1) < 0 && mShaperResponses[io][sec-1]) {
00280 mShaperResponses[io][sector-1] = mShaperResponses[io][sec-1];
00281 break;
00282 }
00283 }
00284 if (! mShaperResponses[io][sector-1]) {
00285 mShaperResponses[io][sector-1] = new TF1F(Form("ShaperFunc_%s_S%02i",Names[io],sector),
00286 StTpcRSMaker::shapeEI3_I,timeBinMin,timeBinMax,7);
00287 mShaperResponses[io][sector-1]->SetParameters(params3);
00288 mShaperResponses[io][sector-1]->SetParNames("t0","tauF","tauP", "tauI", "width","norm","io");
00289 mShaperResponses[io][sector-1]->SetTitle(mShaperResponses[io][sector-1]->GetName());
00290 mShaperResponses[io][sector-1]->GetXaxis()->SetTitle("time (buckets)");
00291 mShaperResponses[io][sector-1]->GetYaxis()->SetTitle("signal");
00292
00293 Double_t t = timeBinMax;
00294 Double_t ymax = mShaperResponses[io][sector-1]->Eval(0.5);
00295 for (; t > 5; t -= 1) {
00296 Double_t r = mShaperResponses[io][sector-1]->Eval(t)/ymax;
00297 if (r > 1e-2) break;
00298 }
00299 mShaperResponses[io][sector-1]->SetRange(timeBinMin,t);
00300 mShaperResponses[io][sector-1]->Save(timeBinMin,t,0,0,0,0);
00301 }
00302 continue;
00303 }
00304
00305 for (Int_t sec = 1; sec < sector; sec++) {
00306 if (St_tpcAltroParamsC::instance()->N(sec-1) >= 0 && mShaperResponses[io][sec-1] ) {
00307 mShaperResponses[io][sector-1] = mShaperResponses[io][sec-1];
00308 break;
00309 }
00310 }
00311 if (! mShaperResponses[io][sector-1]) {
00312 mShaperResponses[io][sector-1] = new TF1F(Form("ShaperFunc_%s_S%02i",Names[io],sector),
00313 StTpcRSMaker::shapeEI_I,timeBinMin,timeBinMax,5);
00314 mShaperResponses[io][sector-1]->SetParameters(params0);
00315 mShaperResponses[io][sector-1]->SetParNames("t0","tauI", "width","norm","io");
00316 mShaperResponses[io][sector-1]->SetTitle(mShaperResponses[io][sector-1]->GetName());
00317 mShaperResponses[io][sector-1]->GetXaxis()->SetTitle("time (buckets)");
00318 mShaperResponses[io][sector-1]->GetYaxis()->SetTitle("signal");
00319
00320 Double_t t = timeBinMax;
00321 Double_t ymax = mShaperResponses[io][sector-1]->Eval(0.5);
00322 for (; t > 5; t -= 1) {
00323 Double_t r = mShaperResponses[io][sector-1]->Eval(t)/ymax;
00324 if (r > 1e-2) break;
00325 }
00326 mShaperResponses[io][sector-1]->SetRange(timeBinMin,t);
00327 mShaperResponses[io][sector-1]->Save(timeBinMin,t,0,0,0,0);
00328 }
00329 }
00330
00331
00332
00333 if (! mPadResponseFunction[io]) {
00334 Double_t xmaxP = 4.5;
00335 Double_t xminP = -xmaxP;
00336 mPadResponseFunction[io] = new TF1F(io == 0 ? "PadResponseFunctionInner" : "PadResponseFunctionOuter",StTpcRSMaker::PadResponseFunc,xminP,xmaxP,6);
00337 Double_t params[6];
00338 if (! io) {
00339 params[0] = gStTpcDb->PadPlaneGeometry()->innerSectorPadWidth();
00340 params[1] = gStTpcDb->WirePlaneGeometry()->innerSectorAnodeWirePadPlaneSeparation();
00341 params[2] = gStTpcDb->WirePlaneGeometry()->anodeWirePitch();
00342 params[3] = St_TpcResponseSimulatorC::instance()->K3IP();
00343 params[4] = 0;
00344 params[5] = gStTpcDb->PadPlaneGeometry()->innerSectorPadPitch();
00345 } else {
00346 params[0] = gStTpcDb->PadPlaneGeometry()->outerSectorPadWidth();
00347 params[1] = gStTpcDb->WirePlaneGeometry()->outerSectorAnodeWirePadPlaneSeparation();
00348 params[2] = gStTpcDb->WirePlaneGeometry()->anodeWirePitch();
00349 params[3] = St_TpcResponseSimulatorC::instance()->K3OP();
00350 params[4] = 0;
00351 params[5] = gStTpcDb->PadPlaneGeometry()->outerSectorPadPitch();
00352 }
00353 mPadResponseFunction[io]->SetParameters(params);
00354 mPadResponseFunction[io]->SetParNames("PadWidth","Anode-Cathode gap","wire spacing","K3OP","CrossTalk","PadPitch");
00355 mPadResponseFunction[io]->SetTitle(mPadResponseFunction[io]->GetName());
00356 mPadResponseFunction[io]->GetXaxis()->SetTitle("pads");
00357 mPadResponseFunction[io]->GetYaxis()->SetTitle("Signal");
00358
00359 Double_t x = xmaxP;
00360 Double_t ymax = mPadResponseFunction[io]->Eval(0);
00361 for (; x > 1.5; x -= 0.05) {
00362 Double_t r = mPadResponseFunction[io]->Eval(x)/ymax;
00363 if (r > 1e-2) break;
00364 }
00365 mPadResponseFunction[io]->SetRange(-x,x);
00366 mPadResponseFunction[io]->Save(xminP,xmaxP,0,0,0,0);
00367 }
00368 if (! mChargeFraction[io]) {
00369 Double_t xmaxP = 2.5;
00370 Double_t xminP = - xmaxP;
00371 mChargeFraction[io] = new TF1F(io == 0 ? "ChargeFractionInner" : "ChargeFractionOuter",
00372 StTpcRSMaker::PadResponseFunc,xminP,xmaxP,6);
00373 Double_t params[6];
00374 if (! io) {
00375 params[0] = gStTpcDb->PadPlaneGeometry()->innerSectorPadLength();
00376 params[3] = St_TpcResponseSimulatorC::instance()->K3IR();
00377 params[4] = 0;
00378 params[5] = 1.;
00379 } else {
00380 params[0] = gStTpcDb->PadPlaneGeometry()->outerSectorPadLength();
00381 params[3] = St_TpcResponseSimulatorC::instance()->K3OR();
00382 params[4] = 0;
00383 params[5] = 1.;
00384 }
00385 mChargeFraction[io]->SetParameters(params);
00386 mChargeFraction[io]->SetParNames("PadLength","Anode-Cathode gap","wire spacing","K3IR","CrossTalk","RowPitch");
00387 mChargeFraction[io]->SetTitle(mChargeFraction[io]->GetName());
00388 mChargeFraction[io]->GetXaxis()->SetTitle("Distance (cm)");
00389 mChargeFraction[io]->GetYaxis()->SetTitle("Signal");
00390
00391 Double_t x = xmaxP;
00392 Double_t ymax = mChargeFraction[io]->Eval(0);
00393 for (; x > 1.5; x -= 0.05) {
00394 Double_t r = mChargeFraction[io]->Eval(x)/ymax;
00395 if (r > 1e-2) break;
00396 }
00397 mChargeFraction[io]->SetRange(-x,x);
00398
00399 mChargeFraction[io]->Save(xminP,xmaxP,0,0,0,0);
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 Double_t gamma;
00414 if (!io ) gamma = St_TpcResponseSimulatorC::instance()->PolyaInner();
00415 else gamma = St_TpcResponseSimulatorC::instance()->PolyaOuter();
00416 if (gamma <= 0) gamma = 1.38;
00417 mPolya[io] = new TF1F(io == 0 ? "PolyaInner;x = G/G_0;signal" : "PolyaOuter;x = G/G_0;signal",polya,0,10,3);
00418 mPolya[io]->SetParameters(gamma, 0., 1./gamma);
00419 }
00420
00421 mGG = new TF1F("GaitingGridTransperency","1-6.27594134307865925e+00*TMath::Exp(-2.87987e-01*(x-1.46222e+01))",21,56);
00422 if (Debug()) Print();
00423 #ifdef __ClusterProfile__
00424 memset (hist, 0, sizeof(hist));
00425 memset (checkList, 0, sizeof(checkList));
00426 if (GetTFile()) {
00427 GetTFile()->cd();
00428 } else {
00429 new TFile("TpcRSCheckList.root","recreate");
00430 }
00431 Int_t color = 1;
00432 struct Name_t {
00433 const Char_t *Name;
00434 const Char_t *Title;
00435 };
00436 const Name_t InOut[6] = {
00437 {"Inner","Inner old electronics"},
00438 {"Outer","Outer old electronics"},
00439 {"InnerX","Inner new electronics"},
00440 {"OuterX","Outer new electronics"},
00441 {"I","Inner"},
00442 {"O","Outer"}
00443 };
00444 const Name_t PadTime[2] = {
00445 {"Pad","Pad"},
00446 {"Time","Time"},
00447 };
00448 for (Int_t io = 0; io < 4; io++) {
00449 for (Int_t pt = 0; pt < 2; pt++) {
00450 TString Name(InOut[io].Name); Name += PadTime[pt].Name; Name += "Mc";
00451 TString Title(InOut[io].Title); Title += PadTime[pt].Title; Title += "Mc";
00452 hist[io][pt] = (TProfile2D *) gDirectory->Get(Name);
00453 if (! hist[io][pt]) {
00454 hist[io][pt] = new TProfile2D(Name,Title,nx[pt],xmin[pt],xmax[pt],nz,zmin,zmax,"");
00455 hist[io][pt]->SetMarkerStyle(20);
00456 hist[io][pt]->SetMarkerColor(color++);
00457 }
00458 }
00459 }
00460 const Name_t Checks[20] = {
00461 {"dEGeant","dE in Geant"},
00462 {"dSGeant","ds in Geant"},
00463 {"Gain","Gas Gain after Voltage"},
00464 {"GainMc","Gas Gain after MC correction"},
00465 {"dEdxCor","correction of dEdx"},
00466 {"lgam","lgam"},
00467 {"NPGEANT","no. of primary electros from GEANT"},
00468 {"NP","no. of primary electros"},
00469 {"Nt","total no. of electors per cluster"},
00470 {"Qav","Gas gain flactuations"},
00471 {"localYDirectionCoupling","localYDirectionCoupling"},
00472 {"n0","No. electrons per primary interaction"},
00473 {"padGain","padGain"},
00474 {"localXDirectionCoupling","localXDirectionCoupling"},
00475 {"XYcoupling","XYcoupling"},
00476 {"dE","dE"},
00477 {"dS","dS"},
00478 {"adc","adc"},
00479 {"NE","Total no. of generated electors"}
00480 };
00481 for (Int_t io = 0; io < 2; io++) {
00482 for (Int_t i = 0; i < nChecks; i++) {
00483 TString Name(Checks[i].Name); Name += InOut[4+io].Name;
00484 TString Title(Checks[i].Title); Title += InOut[4+io].Title;
00485 if (i != 11) checkList[io][i] = new TProfile(Name,Title,nz,zmin,zmax,"");
00486 else checkList[io][i] = new TH2D(Name,Title,nz,zmin,zmax,100,-0.5,99.5);
00487 }
00488 }
00489 #endif
00490 mHeed = fEc(St_TpcResponseSimulatorC::instance()->W());
00491 return kStOK;
00492 }
00493
00494 Int_t StTpcRSMaker::Make(){
00495
00496 #ifdef __DEBUG__
00497 static Int_t iBreak = 0;
00498 static Int_t iSec = 0, iRow = 0;
00499 #endif
00500 static StTpcCoordinateTransform transform(gStTpcDb);
00501 #if defined(__PAD_BLOCK__) || defined(__ClusterProfile__)
00502 enum {kPadMax = 32, kTimeBacketMax = 64};
00503 #endif
00504 #ifdef __PAD_BLOCK__
00505 static Double_t XDirectionCouplings[kPadMax];
00506 static Double_t TimeCouplings[kTimeBacketMax];
00507 #endif
00508 Int_t Ndebug = 0, Idebug;
00509 if (Debug()%10) {
00510 if (Debug()%10 > 1) Ndebug = 10;
00511 gBenchmark->Reset();
00512 gBenchmark->Start("TpcRS");
00513 LOG_INFO << "\n -- Begin TpcRS Processing -- \n";
00514 }
00515 St_g2t_tpc_hit *g2t_tpc_hit = (St_g2t_tpc_hit *) GetDataSet("geant/g2t_tpc_hit");
00516 if (!g2t_tpc_hit) return kStWarn;
00517 Int_t no_tpc_hits = g2t_tpc_hit->GetNRows(); if (no_tpc_hits<1) return kStOK;
00518 if (Debug() > 1) g2t_tpc_hit->Print(0,10);
00519 St_g2t_track *g2t_track = (St_g2t_track *) GetDataSet("geant/g2t_track");
00520 g2t_track_st *tpc_track = 0;
00521 if (g2t_track) tpc_track = g2t_track->GetTable();
00522 St_g2t_vertex *g2t_ver = (St_g2t_vertex *) GetDataSet("geant/g2t_vertex");
00523 g2t_vertex_st *gver = 0;
00524 if (g2t_ver) gver = g2t_ver->GetTable();
00525 g2t_tpc_hit_st *tpc_hit_begin = g2t_tpc_hit->GetTable();
00526 g2t_tpc_hit_st *tpc_hit = tpc_hit_begin;
00527
00528 TTableSorter sorter(g2t_tpc_hit,&SearchT,&CompareT);
00529 Int_t sortedIndex = 0;
00530 tpc_hit = tpc_hit_begin;
00531 for (Int_t sector = 1; sector <= NoOfSectors; sector++) {
00532 Idebug = 0;
00533 Int_t NoHitsInTheSector = 0;
00534 SignalSum_t *SignalSum = ResetSignalSum();
00535
00536 while (sortedIndex < no_tpc_hits) {
00537 Int_t indx = sorter.GetIndex(sortedIndex);
00538 if (indx < 0) break;
00539 tpc_hit = tpc_hit_begin + indx;
00540 Int_t volId = tpc_hit->volume_id%100000;
00541 Int_t iSector = volId/100;
00542 if (iSector != sector) {
00543 if (! ( iSector > sector ) )
00544 LOG_ERROR << "StTpcRSMaker::Make: g2t_tpc_hit table has not been ordered by sector no. !" << endm;
00545 assert( iSector > sector );
00546 break;
00547 }
00548 #ifdef __DEBUG__
00549 if (Debug() && iSec && iSec != sector) {sortedIndex++; continue;}
00550 #endif
00551 if (tpc_hit->volume_id <= 0 || tpc_hit->volume_id > 1000000) {sortedIndex++; continue;}
00552 Int_t Id = tpc_hit->track_p;
00553 Int_t id3 = 0, ipart = 8, charge = 1;
00554 Double_t mass = 0;
00555 if (tpc_track) {
00556 id3 = tpc_track[Id-1].start_vertex_p;
00557 ipart = tpc_track[Id-1].ge_pid;
00558 charge = (Int_t) tpc_track[Id-1].charge;
00559 StParticleDefinition *particle = StParticleTable::instance()->findParticleByGeantId(ipart);
00560 if (particle) {
00561 mass = particle->mass();
00562 charge = particle->charge();
00563 }
00564 #if 0
00565 if (tpc_track[Id-1].next_parent_p && ipart == 3) {
00566 Id = tpc_track[Id-1].next_parent_p;
00567 ipart = tpc_track[Id-1].ge_pid;
00568 }
00569 #endif
00570
00571 }
00572 if (ipart == Laserino || ipart == Chasrino) {
00573 charge = 0;
00574 } else {
00575 if (ipart == 1) {
00576 ipart = 3;
00577 charge = -1;
00578 }
00579 if (charge == 0) {
00580 sortedIndex++;
00581 continue;
00582 }
00583 }
00584
00585 struct HitPoint_t {
00586 Int_t indx;
00587 Int_t TrackId;
00588 Double_t s;
00589 Double_t sMin, sMax;
00590 g2t_tpc_hit_st *tpc_hitC;
00591 StGlobalCoordinate xyzG;
00592 StTpcLocalSectorCoordinate coorLS;
00593 StTpcLocalSectorDirection dirLS, BLS;
00594 StTpcPadCoordinate Pad;
00595 };
00596 static HitPoint_t TrackSegmentHits[40];
00597 static TRVector Pred;
00598 Double_t sMin = 9999;
00599 Double_t sMax = -9999;
00600 Int_t nSegHits = 0;
00601 Int_t sIndex = sortedIndex;
00602 Int_t io = -1;
00603 for (nSegHits = 0, sIndex = sortedIndex; sIndex < no_tpc_hits && nSegHits < 40; sIndex++) {
00604 indx = sorter.GetIndex(sIndex);
00605 g2t_tpc_hit_st *tpc_hitC = tpc_hit_begin + indx;
00606 if ((tpc_hitC->volume_id%100000)/100 != sector) break;
00607 if ( tpc_hitC->track_p != tpc_hit->track_p) break;
00608 Int_t row = tpc_hitC->volume_id%100;
00609 Int_t ior = (row <= NoOfInnerRows) ? 0 : 1;
00610 if (io >= 0 && io != ior) break;
00611 io = ior;
00612 TrackSegmentHits[nSegHits].TrackId = Id;
00613 TrackSegmentHits[nSegHits].tpc_hitC = tpc_hitC;
00614 TrackSegmentHits[nSegHits].indx = indx;
00615 TrackSegmentHits[nSegHits].s = tpc_hitC->length;
00616 if (tpc_hitC->length == 0 && nSegHits > 0) {
00617 TrackSegmentHits[nSegHits].s = TrackSegmentHits[nSegHits-1].s + TrackSegmentHits[nSegHits].tpc_hitC->ds;
00618 }
00619 #ifdef __ClusterProfile__
00620 checkList[io][0]->Fill(TrackSegmentHits[nSegHits].tpc_hitC->x[2],TMath::Abs(TrackSegmentHits[nSegHits].tpc_hitC->de));
00621 checkList[io][1]->Fill(TrackSegmentHits[nSegHits].tpc_hitC->x[2], TrackSegmentHits[nSegHits].tpc_hitC->ds );
00622 #endif
00623 TrackSegmentHits[nSegHits].sMin = TrackSegmentHits[nSegHits].s - TrackSegmentHits[nSegHits].tpc_hitC->ds;
00624 TrackSegmentHits[nSegHits].sMax = TrackSegmentHits[nSegHits].s;
00625 if (TrackSegmentHits[nSegHits].sMin < sMin) sMin = TrackSegmentHits[nSegHits].sMin;
00626 if (TrackSegmentHits[nSegHits].sMax > sMax) sMax = TrackSegmentHits[nSegHits].sMax;
00627
00628 static Float_t BFieldG[3];
00629 StMagF::Agufld(tpc_hitC->x,BFieldG);
00630
00631 TrackSegmentHits[nSegHits].xyzG =
00632 StGlobalCoordinate(tpc_hitC->x[0],tpc_hitC->x[1],tpc_hitC->x[2]); PrPP(Make,TrackSegmentHits[nSegHits].xyzG);
00633
00634 StThreeVectorD pxyzG(tpc_hitC->p[0],tpc_hitC->p[1],tpc_hitC->p[2]);
00635 StGlobalDirection dirG(pxyzG.unit()); PrPP(Make,dirG);
00636 StGlobalDirection BG(BFieldG[0],BFieldG[1],BFieldG[2]); PrPP(Make,BG);
00637 static StGlobalCoordinate coorG;
00638 coorG = TrackSegmentHits[nSegHits].xyzG;
00639 static StTpcLocalCoordinate coorLT;
00640 static StTpcLocalDirection dirLT, BLT;
00641 transform(coorG, coorLT,sector,row); PrPP(Make,coorLT);
00642 transform( dirG, dirLT,sector,row); PrPP(Make,dirLT);
00643 transform( BG, BLT,sector,row); PrPP(Make,BLT);
00644
00645 static StTpcLocalCoordinate coorLTD;
00646 coorLTD = coorLT;
00647 if (TESTBIT(m_Mode, kDistortion) && StMagUtilities::Instance()) {
00648 Float_t pos[3] = {coorLTD.position().x(), coorLTD.position().y(), coorLTD.position().z()};
00649 Float_t posMoved[3];
00650 StMagUtilities::Instance()->DoDistortion(pos,posMoved);
00651 StThreeVector<double> postion(posMoved[0],posMoved[1],posMoved[2]);
00652 coorLT.setPosition(postion);
00653 transform(coorLT,TrackSegmentHits[nSegHits].xyzG); PrPP(Make,coorLT);
00654 }
00655
00656 static StTpcLocalSectorAlignedCoordinate coorLSA;
00657 static StTpcLocalSectorAlignedDirection dirLSA, BLSA;
00658 transform(coorLT,coorLSA); PrPP(Make,coorLSA);
00659 transform( dirLT, dirLSA); PrPP(Make,dirLSA);
00660 transform( BLT, BLSA); PrPP(Make,BLSA);
00661 static StTpcLocalSectorCoordinate coorLS;
00662 static StTpcLocalSectorDirection dirLS, BLS;
00663 transform(coorLSA,TrackSegmentHits[nSegHits].coorLS); PrPP(Make,TrackSegmentHits[nSegHits].coorLS);
00664 transform( dirLSA, TrackSegmentHits[nSegHits].dirLS); PrPP(Make,TrackSegmentHits[nSegHits].dirLS);
00665 transform( BLSA, TrackSegmentHits[nSegHits].BLS); PrPP(Make,TrackSegmentHits[nSegHits].BLS);
00666 Double_t tof = 0;
00667 if (gver) tof = gver[id3-1].ge_tof;
00668 if (! TESTBIT(m_Mode, kNoToflight)) tof += tpc_hit->tof;
00669 Double_t driftLength = TrackSegmentHits[nSegHits].coorLS.position().z() + tof*gStTpcDb->DriftVelocity(sector);
00670
00671 if (driftLength > 250. || driftLength < -1.0) {continue;}
00672 if (driftLength <= 0) {
00673 if ((row > NoOfInnerRows && driftLength > -gStTpcDb->WirePlaneGeometry()->outerSectorAnodeWirePadPlaneSeparation()) ||
00674 (row <= NoOfInnerRows && driftLength > -gStTpcDb->WirePlaneGeometry()->innerSectorAnodeWirePadPlaneSeparation()))
00675 driftLength = TMath::Abs(driftLength);
00676 else {continue;}
00677 }
00678 TrackSegmentHits[nSegHits].coorLS.position().setZ(driftLength); PrPP(Make,TrackSegmentHits[nSegHits].coorLS);
00679
00680 transform(TrackSegmentHits[nSegHits].coorLS,TrackSegmentHits[nSegHits].Pad,kFALSE,kFALSE);
00681 PrPP(Make,TrackSegmentHits[nSegHits].Pad);
00682 if (TrackSegmentHits[nSegHits].Pad.timeBucket() < 0 || TrackSegmentHits[nSegHits].Pad.timeBucket() > NoOfTimeBins) continue;
00683 nSegHits++;
00684 }
00685 sortedIndex = sIndex;
00686
00687
00688 Int_t iowe = 0;
00689 if (sector > 12) iowe += 4;
00690 if (io) iowe += 2;
00691 Float_t *AdditionalMcCorrection = St_TpcResponseSimulatorC::instance()->SecRowCor();
00692 Float_t *AddSigmaMcCorrection = St_TpcResponseSimulatorC::instance()->SecRowSig();
00693
00694 Double_t padlength = gStTpcDb->PadPlaneGeometry()->innerSectorPadLength();
00695 Double_t PadPitch = gStTpcDb->PadPlaneGeometry()->innerSectorPadPitch();
00696 Double_t sigmaJitterT = St_TpcResponseSimulatorC::instance()->SigmaJitterTI();
00697 Double_t sigmaJitterX = St_TpcResponseSimulatorC::instance()->SigmaJitterXI();
00698 if(io) {
00699 padlength = gStTpcDb->PadPlaneGeometry()->outerSectorPadLength();
00700 PadPitch = gStTpcDb->PadPlaneGeometry()->outerSectorPadPitch();
00701 sigmaJitterT = St_TpcResponseSimulatorC::instance()->SigmaJitterTO();
00702 sigmaJitterX = St_TpcResponseSimulatorC::instance()->SigmaJitterXO();
00703 }
00704 Double_t s = sMin;
00705 for (Int_t iSegHits = 0; iSegHits < nSegHits && s < sMax; iSegHits++) {
00706 g2t_tpc_hit_st *tpc_hitC = TrackSegmentHits[iSegHits].tpc_hitC;
00707 volId = tpc_hitC->volume_id%100000;
00708 Int_t row = volId%100;
00709 #ifdef __DEBUG__
00710 if (Debug() && iRow && iRow != row) continue;
00711 #endif
00712 io = (row <= NoOfInnerRows) ? 0 : 1;
00713
00714 Double_t Gain = St_tss_tssparC::instance()->gain(sector,row);
00715 TF1F *mShaperResponse = mShaperResponses[io][sector-1];
00716 Int_t rowMin = row;
00717 Int_t rowMax = row;
00718 if(row > NoOfInnerRows) {
00719 rowMin = TMath::Max(row - 1, NoOfInnerRows+1);
00720 rowMax = TMath::Min(row + 1, NoOfRows);
00721 }
00722 #ifdef __ClusterProfile__
00723 checkList[io][2]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),Gain);
00724 #endif
00725 Double_t GainXCorrectionL = AdditionalMcCorrection[iowe] + row*AdditionalMcCorrection[iowe+1];
00726 Gain *= TMath::Exp(-GainXCorrectionL);
00727 Double_t GainXSigma = AddSigmaMcCorrection[iowe] + row*AddSigmaMcCorrection[iowe+1];
00728 if (GainXSigma > 0) Gain *= TMath::Exp(gRandom->Gaus(0.,GainXSigma));
00729 #ifdef __ClusterProfile__
00730 checkList[io][3]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),Gain);
00731 #endif
00732
00733 Double_t dEdxCor = 1;
00734 Double_t dStep = TMath::Abs(tpc_hitC->ds);
00735 if (m_TpcdEdxCorrection) {
00736 dEdxY2_t CdEdx;
00737 memset (&CdEdx, 0, sizeof(dEdxY2_t));
00738 CdEdx.sector = TrackSegmentHits[iSegHits].Pad.sector();
00739 CdEdx.row = TrackSegmentHits[iSegHits].Pad.row();
00740 CdEdx.pad = TMath::Nint(TrackSegmentHits[iSegHits].Pad.pad());
00741 Double_t edge = CdEdx.pad;
00742 if (edge > 0.5*gStTpcDb->PadPlaneGeometry()->numberOfPadsAtRow(CdEdx.row))
00743 edge -= gStTpcDb->PadPlaneGeometry()->numberOfPadsAtRow(CdEdx.row) + 1;
00744 CdEdx.edge = edge;
00745 CdEdx.dE = 1;
00746 CdEdx.dx = dStep;
00747 CdEdx.xyz[0] = TrackSegmentHits[iSegHits].xyzG.position().x();
00748 CdEdx.xyz[1] = TrackSegmentHits[iSegHits].xyzG.position().y();
00749 CdEdx.xyz[2] = TrackSegmentHits[iSegHits].xyzG.position().z();
00750 CdEdx.ZdriftDistance = TrackSegmentHits[iSegHits].coorLS.position().z();
00751 St_tpcGas *tpcGas = m_TpcdEdxCorrection->tpcGas();
00752 if (tpcGas)
00753 CdEdx.ZdriftDistanceO2 = CdEdx.ZdriftDistance*(*tpcGas)[0].ppmOxygenIn;
00754 if (! m_TpcdEdxCorrection->dEdxCorrection(CdEdx)) {
00755 dEdxCor = CdEdx.dE;
00756 }
00757 if (dEdxCor <= 0.) continue;
00758 }
00759 #ifdef __ClusterProfile__
00760 checkList[io][4]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),dEdxCor);
00761 #endif
00762
00763 if (TrackSegmentHits[iSegHits].Pad.timeBucket() > mGG->GetXmin() &&
00764 TrackSegmentHits[iSegHits].Pad.timeBucket() < mGG->GetXmax()) {
00765 dEdxCor *= mGG->Eval(TrackSegmentHits[iSegHits].Pad.timeBucket());
00766 }
00767 if (dEdxCor < minSignal) continue;
00768
00769 Float_t BField[3] = {TrackSegmentHits[iSegHits].BLS.position().x(),
00770 TrackSegmentHits[iSegHits].BLS.position().y(),
00771 TrackSegmentHits[iSegHits].BLS.position().z()};
00772 StPhysicalHelixD track(TrackSegmentHits[iSegHits].dirLS.position(),
00773 TrackSegmentHits[iSegHits].coorLS.position(),
00774 BField[2]*kilogauss*charge,1);
00775 StThreeVectorD unit = track.momentum(0).unit();
00776 Double_t *cxyz = unit.xyz();
00777 TRMatrix L2L(3,3,
00778 cxyz[2], - cxyz[0]*cxyz[2] , cxyz[0],
00779 cxyz[0], - cxyz[1]*cxyz[2] , cxyz[1],
00780 0.0 , cxyz[0]*cxyz[0] + cxyz[1]*cxyz[1], cxyz[2]);
00781 #ifdef __DEBUG__
00782 if (Debug() % 10 > 1) PrPP(Make,track);
00783 #endif
00784 Double_t s_low = -dStep/2;
00785 Double_t s_upper = s_low + dStep;
00786 Double_t newPosition = s_low;
00787 static StThreeVectorD normal(0,1,0);
00788 StThreeVectorD rowPlane(0,transform.yFromRow(TrackSegmentHits[iSegHits].Pad.row()),0);
00789 Double_t sR = track.pathLength(rowPlane,normal);
00790 if (sR < 1e10) {
00791 PrPP(Maker,sR);
00792 PrPP(Make,TrackSegmentHits[iSegHits].coorLS);
00793 StThreeVectorD xyzP = track.at(sR);
00794 TrackSegmentHits[iSegHits].coorLS.setPosition(xyzP); PrPP(Make,TrackSegmentHits[iSegHits].coorLS);
00795
00796 PrPP(Make,TrackSegmentHits[iSegHits].Pad);
00797 transform(TrackSegmentHits[iSegHits].coorLS,TrackSegmentHits[iSegHits].Pad,kFALSE,kFALSE);
00798 PrPP(Make,TrackSegmentHits[iSegHits].Pad);
00799 }
00800 Int_t ioH = io;
00801 if (St_tpcAltroParamsC::instance()->N(sector-1) >= 0) ioH += 2;
00802 Double_t TotalSignal = 0;
00803 Double_t lgam = tpc_hitC->lgam;
00804 #ifdef __ClusterProfile__
00805 checkList[io][5]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),lgam);
00806 #endif
00807 Double_t gamma = TMath::Power(10.,lgam) + 1;
00808 Double_t betaGamma = TMath::Sqrt(gamma*gamma - 1.);
00809 StThreeVectorD pxyzG(tpc_hitC->p[0],tpc_hitC->p[1],tpc_hitC->p[2]);
00810 Double_t bg = 0;
00811 if (mass > 0) bg = pxyzG.mag()/mass;
00812 if (bg > betaGamma) betaGamma = bg;
00813 Double_t bg2 = betaGamma*betaGamma;
00814 gamma = TMath::Sqrt(bg2 + 1.);
00815 static const Double_t m_e = .51099907e-3;
00816 Double_t Tmax;
00817 if (mass < 2*m_e) {
00818 if (charge > 0) Tmax = m_e*(gamma - 1);
00819 else Tmax = 0.5*m_e*(gamma - 1);
00820 } else {
00821 Double_t r = m_e/mass;
00822 Tmax = 2*m_e*bg2/(1 + 2*gamma*r + r*r);
00823 }
00824 if (Tmax > mCutEle) Tmax = mCutEle;
00825 Double_t padH = TrackSegmentHits[iSegHits].Pad.pad();
00826 Double_t tbkH = TrackSegmentHits[iSegHits].Pad.timeBucket();
00827 tpc_hitC->pad = padH;
00828 tpc_hitC->timebucket = tbkH;
00829 #ifdef __ClusterProfile__
00830 Int_t pad0 = TMath::Nint(padH + xmin[0]);
00831 Int_t tbk0 = TMath::Nint(tbkH + xmin[1]);
00832 #endif
00833 Double_t OmegaTau =St_TpcResponseSimulatorC::instance()->OmegaTau()*
00834 TrackSegmentHits[iSegHits].BLS.position().z()/5.0;
00835 Double_t NP = TMath::Abs(tpc_hitC->de/tpc_hitC->ds)/(St_TpcResponseSimulatorC::instance()->W()*eV*
00836 St_TpcResponseSimulatorC::instance()->Cluster());
00837 #ifdef __ClusterProfile__
00838 checkList[io][6]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),NP);
00839 #endif
00840 Double_t driftLength = TMath::Abs(TrackSegmentHits[iSegHits].coorLS.position().z());
00841 Double_t D = 1. + OmegaTau*OmegaTau;
00842 Double_t SigmaT = St_TpcResponseSimulatorC::instance()->transverseDiffusion()* TMath::Sqrt( driftLength/D);
00843
00844 if (sigmaJitterX > 0) {SigmaT = TMath::Sqrt(SigmaT*SigmaT + sigmaJitterX*sigmaJitterX);}
00845 Double_t SigmaL = St_TpcResponseSimulatorC::instance()->longitudinalDiffusion()*TMath::Sqrt( driftLength );
00846 Double_t GainLocal = Gain/dEdxCor/St_TpcResponseSimulatorC::instance()->NoElPerAdc();
00847
00848
00849 if (TESTBIT(m_Mode, kBICHSEL)) {
00850 NP = GetNoPrimaryClusters(betaGamma,charge);
00851 #ifdef __DEBUG__
00852 if (NP <= 0.0) {
00853 iBreak++; continue;
00854 }
00855 #endif
00856 }
00857 #ifdef __ClusterProfile__
00858 checkList[io][7]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),NP);
00859 #endif
00860 Int_t nP = 0;
00861 Double_t xOnWire, yOnWire, zOnWire;
00862 Double_t dESum = 0;
00863 Double_t dSSum = 0;
00864 Int_t nTotal = 0;
00865 #ifdef __ClusterProfile__
00866 Double_t padsdE[kPadMax]; memset (padsdE, 0, sizeof(padsdE));
00867 Double_t tbksdE[kTimeBacketMax]; memset (tbksdE, 0, sizeof(tbksdE));
00868 #endif
00869 Float_t dEr = 0;
00870 TArrayF rs(10);
00871 do {
00872 Float_t dS = 0;
00873 Float_t dE = 0;
00874 if (charge) {
00875 if (TESTBIT(m_Mode, kPAI)) {
00876 mPAI->xNext(betaGamma,dS,dE);
00877 }
00878 else {
00879 dS = - TMath::Log(gRandom->Rndm())/NP;
00880 if (TESTBIT(m_Mode, kBICHSEL)) dE = TMath::Exp(mdNdE->GetRandom());
00881 else dE = St_TpcResponseSimulatorC::instance()->W()*
00882 gRandom->Poisson(St_TpcResponseSimulatorC::instance()->Cluster());
00883 }
00884 }
00885 else {
00886
00887 dE = 10;
00888 dS = dE*eV/(TMath::Abs(mLaserScale*tpc_hitC->de/tpc_hitC->ds));
00889 }
00890 #ifdef __DEBUG__
00891 if (Debug()%10 > 1) {
00892 LOG_INFO << "s_low/s_upper/dSD\t" << s_low << "/\t" << s_upper << "\t" << dS << endm;
00893 }
00894 #endif
00895 Double_t E = dE*eV;
00896 if (dE < St_TpcResponseSimulatorC::instance()->W()/2 || E > Tmax) continue;
00897 dESum += dE;
00898 dSSum += dS;
00899 nP++;
00900 newPosition += dS;
00901 #ifdef __DEBUG__
00902 if (Debug()%10 > 2) {
00903 LOG_INFO << "dESum = " << dESum << " /\tdSSum " << dSSum << " /\t newPostion " << newPosition << endm;
00904 }
00905 #endif
00906 if (newPosition > s_upper) break;
00907 Double_t xRange = 0;
00908 if (dE > ElectronRangeEnergy) xRange = ElectronRange*TMath::Power((dE+dEr)/ElectronRangeEnergy,ElectronRangePower);
00909 Int_t Nt = 0;
00910 Float_t dET = dE + dEr;
00911 dEr = dET;
00912 Float_t EC;
00913 Int_t Nr = 0;
00914 if (xRange > 0) {Nr = rs.GetSize();}
00915 while ((EC = mHeed->GetRandom()) < dEr) {
00916 dEr -= EC;
00917 if (Nr) {
00918 if (Nr <= Nt) {Nr = 2*Nt+1; rs.Set(Nr); }
00919 rs[Nt] = 1 - dEr/dET;
00920 }
00921 Nt++;
00922 }
00923 if (! Nt) continue;
00924 #ifdef __ClusterProfile__
00925 checkList[io][8]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),Nt);
00926 checkList[io][11]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),Nt);
00927 #endif
00928 StThreeVectorD xyzC = track.at(newPosition);
00929 Double_t phiXY = 2*TMath::Pi()*gRandom->Rndm();
00930 Double_t rX = TMath::Cos(phiXY);
00931 Double_t rY = TMath::Sin(phiXY);
00932 Double_t sigmaT = SigmaT;
00933 Double_t sigmaL = SigmaL;
00934 for (Int_t ie = 0; ie < Nt; ie++) {
00935 nTotal++;
00936 Double_t QAv = mPolya[io]->GetRandom();
00937
00938 gRandom->Rannor(rX,rY);
00939 StTpcLocalSectorCoordinate xyzE(xyzC.x()+rX*sigmaT,
00940 xyzC.y()+rY*sigmaT,
00941 xyzC.z()+gRandom->Gaus(0,sigmaL), sector, row);
00942 if (xRange > 0) {
00943 Double_t xR = rs[ie]*xRange;
00944 TRVector xyzRangeL(3, xR*rX, xR*rY, 0.);
00945 TRVector xyzR(L2L,TRArray::kAxB,xyzRangeL);
00946 #ifdef __DEBUG__
00947 if (Debug()%10 > 2) {
00948 LOG_INFO << "xyzRangeL: " << xyzRangeL << endm;
00949 LOG_INFO << "L2L: " << L2L << endm;
00950 LOG_INFO << "xyzR: " << xyzR << endm;
00951 }
00952 #endif
00953 TCL::vadd(xyzE.position().xyz(),xyzR.GetArray(),xyzE.position().xyz(),3);
00954 }
00955 Double_t y = xyzE.position().y();
00956 Double_t alphaVariation = InnerAlphaVariation;
00957
00958 if (y < firstInnerSectorAnodeWire || y > lastOuterSectorAnodeWire) continue;
00959 if (y > lastInnerSectorAnodeWire && y < firstOuterSectorAnodeWire) continue;
00960 if (y < lastInnerSectorAnodeWire) {
00961 Int_t WireIndex = TMath::Nint((y - firstInnerSectorAnodeWire)/anodeWirePitch);
00962 yOnWire = firstInnerSectorAnodeWire + WireIndex*anodeWirePitch;
00963 }
00964 else {
00965 Int_t WireIndex = TMath::Nint((y - firstOuterSectorAnodeWire)/anodeWirePitch);
00966 yOnWire = firstOuterSectorAnodeWire + WireIndex*anodeWirePitch;
00967 alphaVariation = OuterAlphaVariation;
00968 }
00969 Double_t distanceToWire = y - yOnWire;
00970 xOnWire = xyzE.position().x();
00971 zOnWire = xyzE.position().z();
00972
00973 Int_t iGridWire = (Int_t ) TMath::Abs(10.*distanceToWire);
00974 Double_t dist2Grid = TMath::Sign(0.05 + 0.1*iGridWire, distanceToWire);
00975
00976 Int_t iGroundWire = (Int_t ) TMath::Abs(10.*dist2Grid);
00977 Double_t distFocused = TMath::Sign(0.05 + 0.1*iGroundWire, dist2Grid);
00978
00979 Double_t tanLorentz = OmegaTau/St_TpcResponseSimulatorC::instance()->OmegaTauScaleO();
00980 if (y < firstOuterSectorAnodeWire) tanLorentz = OmegaTau/St_TpcResponseSimulatorC::instance()->OmegaTauScaleI();
00981 xOnWire += distFocused*tanLorentz;
00982 zOnWire += TMath::Abs(distFocused);
00983 if (! iGroundWire ) QAv *= TMath::Exp( alphaVariation);
00984 else QAv *= TMath::Exp(-alphaVariation);
00985 #ifdef __ClusterProfile__
00986 checkList[io][9]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),QAv);
00987 #endif
00988 for(Int_t r = rowMin; r <= rowMax; r++) {
00989 Int_t iRdo = StDetectorDbTpcRDOMasks::instance()->rdoForPadrow(r);
00990 if ( ! StDetectorDbTpcRDOMasks::instance()->isOn(sector,iRdo)) continue;
00991 if ( ! St_tpcAnodeHVavgC::instance()->livePadrow(sector,r)) continue;
00992 StTpcLocalSectorCoordinate xyzW(xOnWire, yOnWire, zOnWire, sector, r);
00993 static StTpcPadCoordinate Pad;
00994 transform(xyzW,Pad,kFALSE,kFALSE);
00995 Float_t bin = Pad.timeBucket();
00996 Int_t binT = TMath::Nint(bin);
00997 if (binT < 0 || binT >= NoOfTimeBins) continue;
00998 Double_t dT = bin - binT + St_TpcResponseSimulatorC::instance()->T0offset();
00999 if (sigmaJitterT) dT += gRandom->Gaus(0,sigmaJitterT);
01000 Double_t dely[1] = {transform.yFromRow(r)-yOnWire};
01001 Double_t localYDirectionCoupling = mChargeFraction[io]->GetSaveL(dely);
01002 #ifdef __ClusterProfile__
01003 checkList[io][10]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),localYDirectionCoupling);
01004 #endif
01005 if(localYDirectionCoupling < minSignal) continue;
01006 Float_t padX = Pad.pad();
01007 Int_t CentralPad = TMath::Nint(padX);
01008 if (CentralPad < 1) continue;
01009 Int_t PadsAtRow = gStTpcDb->PadPlaneGeometry()->numberOfPadsAtRow(r);
01010 if(CentralPad > PadsAtRow) continue;
01011 Int_t DeltaPad = TMath::Nint(mPadResponseFunction[io]->GetXmax());
01012 Int_t padMin = TMath::Max(CentralPad - DeltaPad ,1);
01013 Int_t padMax = TMath::Min(CentralPad + DeltaPad ,PadsAtRow);
01014 #ifdef __PAD_BLOCK__
01015 Int_t Npads = TMath::Min(padMax-padMin+1, kPadMax);
01016 Double_t xPadMin = padMin - padX;
01017 mPadResponseFunction[io]->GetSaveL(Npads,xPadMin,XDirectionCouplings);
01018 #endif
01019
01020 for(Int_t pad = padMin; pad <= padMax; pad++) {
01021 Double_t gain = QAv*GainLocal;
01022 Double_t dt = dT;
01023 if (! TESTBIT(m_Mode, kGAINOAtALL)) {
01024 gain *= St_tpcPadGainT0C::instance()->Gain(sector,r,pad);
01025 if (gain <= 0.0) continue;
01026 dt -= St_tpcPadGainT0C::instance()->T0(sector,r,pad);
01027 }
01028 #ifdef __ClusterProfile__
01029 checkList[io][12]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),gain);
01030 #endif
01031 #ifdef __PAD_BLOCK__
01032
01033 Double_t localXDirectionCoupling = gain*XDirectionCouplings[pad-padMin];
01034 #else
01035 Double_t xPad = pad - padX;
01036 Double_t xpad[1] = {xPad};
01037 Double_t localXDirectionCoupling = gain*mPadResponseFunction[io]->GetSaveL(xpad);
01038 #endif
01039 if (localXDirectionCoupling < minSignal) continue;
01040 #ifdef __ClusterProfile__
01041 checkList[io][13]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),localXDirectionCoupling);
01042 #endif
01043 Double_t XYcoupling = localYDirectionCoupling*localXDirectionCoupling;
01044 #ifdef __ClusterProfile__
01045 checkList[io][14]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),XYcoupling);
01046 #endif
01047 if(XYcoupling < minSignal) continue;
01048 Int_t bin_low = TMath::Max(0 ,binT + TMath::Nint(dt+mShaperResponse->GetXmin()-0.5));
01049 Int_t bin_high = TMath::Min(NoOfTimeBins-1,binT + TMath::Nint(dt+mShaperResponse->GetXmax()+0.5));
01050 Int_t index = NoOfTimeBins*((r-1)*NoOfPads+pad-1)+bin_low;
01051 #ifdef __PAD_BLOCK__
01052 Int_t Ntbks = TMath::Min(bin_high-bin_low+1, kTimeBacketMax);
01053 Double_t tt = -dt + (bin_low - binT);
01054 mShaperResponse->GetSaveL(Ntbks,tt,TimeCouplings);
01055 #endif
01056 for(Int_t itbin=bin_low;itbin<=bin_high;itbin++, index++){
01057 #ifdef __PAD_BLOCK__
01058 Double_t signal = XYcoupling*TimeCouplings[itbin-bin_low];
01059 #else
01060 Double_t t = -dt + (Double_t)(itbin - binT);
01061 Double_t signal = XYcoupling*mShaperResponse->GetSaveL(&t);
01062 #endif
01063 if (signal < minSignal) continue;
01064 TotalSignal += signal;
01065 SignalSum[index].Sum += signal;
01066 #ifdef __ClusterProfile__
01067 if (pad >= pad0 && pad < pad0 + kPadMax &&
01068 itbin >= tbk0 && itbin < tbk0 + kTimeBacketMax) {
01069 padsdE[pad-pad0] += signal;
01070 tbksdE[itbin-tbk0] += signal;
01071 }
01072 #endif
01073 if ( TrackSegmentHits[iSegHits].TrackId ) {
01074 if (! SignalSum[index].TrackId ) SignalSum[index].TrackId = TrackSegmentHits[iSegHits].TrackId;
01075 else
01076 if ( SignalSum[index].TrackId != TrackSegmentHits[iSegHits].TrackId && SignalSum[index].Sum < 2*signal)
01077 SignalSum[index].TrackId = TrackSegmentHits[iSegHits].TrackId;
01078 }
01079 #ifdef __ClusterProfile__
01080 #ifdef __DEBUG__
01081 if (Debug()%10 > 2 && (SignalSum[index].Sum > 0 || ! TMath::Finite(SignalSum[index].Sum)) ) {
01082 LOG_INFO << "simu R/P/T/I = " << r << " /\t" << pad << " /\t" << itbin << " /\t" << index
01083 << "\tSum/Adc/TrackId = " << SignalSum[index].Sum << " /\t"
01084 << SignalSum[index].Adc << " /\t" << SignalSum[index].TrackId
01085 << "\tsignal = " << signal << endm;
01086 if (! TMath::Finite(SignalSum[index].Sum)) {
01087 LOG_INFO << "Not Finite" << endm;
01088 }
01089 #endif
01090 }
01091 #endif
01092 }
01093 }
01094 }
01095 }
01096 } while (kTRUE);
01097 tpc_hitC->adc = -99;
01098 if (dESum > 0 && dSSum) {
01099 #ifdef __DEBUG__
01100 if (Debug()%10 > 2) {
01101 LOG_INFO << "sIndex = " << sIndex << " volId = " << volId
01102 << " dESum = " << dESum << " /\tdSSum " << dSSum << " /\t TotalSignal " << TotalSignal << endm;
01103 }
01104 #endif
01105 tpc_hitC->de = dESum*eV;
01106 tpc_hitC->ds = dSSum;
01107 tpc_hitC->adc = TotalSignal;
01108 #ifdef __ClusterProfile__
01109 if (TotalSignal > 0) {
01110 if (hist[ioH][0]) {
01111 for (Int_t p = 0; p < kPadMax; p++)
01112 hist[ioH][0]->Fill((p+pad0)-padH,TrackSegmentHits[iSegHits].xyzG.position().z(),padsdE[p]/TotalSignal);
01113 }
01114 if (hist[ioH][1]) {
01115 for (Int_t t = 0; t < kTimeBacketMax; t++)
01116 hist[ioH][1]->Fill((t+tbk0+0.5)-tbkH,TrackSegmentHits[iSegHits].xyzG.position().z(),tbksdE[t]/TotalSignal);
01117 }
01118 }
01119 checkList[io][15]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),tpc_hitC->de);
01120 checkList[io][16]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),tpc_hitC->ds);
01121 checkList[io][17]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),tpc_hitC->adc);
01122 checkList[io][18]->Fill(TrackSegmentHits[iSegHits].xyzG.position().z(),nTotal);
01123 #endif
01124 }
01125 NoHitsInTheSector++;
01126 }
01127 }
01128 if (NoHitsInTheSector) {
01129 DigitizeSector(sector);
01130 if (Debug()) LOG_INFO << "StTpcRSMaker: Done with sector\t" << sector << " total no. of hit = " << NoHitsInTheSector << endm;
01131 }
01132 }
01133 if (Debug()%10) gBenchmark->Show("TpcRS");
01134 return kStOK;
01135 }
01136
01137 Double_t StTpcRSMaker::GetNoPrimaryClusters(Double_t betaGamma, Int_t charge) {
01138 Double_t beta = betaGamma/TMath::Sqrt(1.0 + betaGamma*betaGamma);
01139 #ifdef Old_dNdx_Table
01140 #ifdef SimpleMindedExtrapolation
01141 static Double_t slope = 8.91704e-01;
01142 static Double_t betaGammaMin = mdNdx->GetBinCenter(1);
01143 static Double_t betaGammaMax = mdNdx->GetXaxis()->GetXmax();
01144 static Double_t betaMin = betaGammaMin/TMath::Sqrt(1.0 - betaGammaMin*betaGammaMin);
01145 Double_t dNdx = mdNdx->Interpolate(betaGamma);
01146 if (betaGamma < betaGammaMin) {
01147 dNdx *= TMath::Power(betaMin/beta,2*slope);
01148 }
01149 if (betaGamma > betaGammaMax) {
01150
01151
01152 dNdx = charge*charge*mdNdx->Interpolate(betaGammaMax) + 1.61623e+00*TMath::Log(betaGamma/betaGammaMax);
01153 }
01154 #else
01155 Double_t dNdx = 1.21773e+01*Bichsel::Instance()->GetI70M(TMath::Log10(betaGamma));
01156 #endif
01157 #else
01158 Double_t dNdx = mdNdx->Interpolate(betaGamma);
01159 #endif
01160 Double_t Q_eff = TMath::Abs(charge);
01161 if (Q_eff > 1) {
01162
01163 Double_t w1 = 1.034 - 0.1777*TMath::Exp(-0.08114*Q_eff);
01164 Double_t w2 = beta*TMath::Power(Q_eff,-2./3.);
01165 Double_t w3 = 121.4139*w2 + 0.0378*TMath::Sin(190.7165*w2);
01166 Q_eff *= 1. -w1*TMath::Exp(-w3);
01167 }
01168 return Q_eff*Q_eff*dNdx;
01169 }
01170
01171 Double_t StTpcRSMaker::ShaperFunc(Double_t *x, Double_t *par) {
01172 Double_t tau = par[0];
01173 Double_t width = par[1];
01174 Double_t p = par[2];
01175 Double_t t = x[0]*width/tau;
01176 Double_t Delta = width/tau;
01177 Double_t t1 = t - Delta/2.;
01178 Double_t t2 = t1 + Delta;
01179 Double_t val = TMath::Gamma(p,t2) - TMath::Gamma(p,t1);
01180 return val;
01181 }
01182
01183 Double_t StTpcRSMaker::PadResponseFunc(Double_t *x, Double_t *par) {
01184 Double_t CrossTalk = 0;
01185 Double_t Value = 0;
01186 Double_t X = par[5]*x[0];
01187 if (CrossTalk > 0) {
01188 for (Int_t i = -1; i <= 1; i++) {
01189 Double_t xx = X + par[5]*i;
01190 if (i == 0) Value += (1. - 2.*CrossTalk)*Gatti(&xx,par);
01191 else Value += CrossTalk *Gatti(&xx,par);
01192 }
01193 } else Value = Gatti(&X,par);
01194 return Value;
01195 }
01196
01197 Double_t StTpcRSMaker::Gatti(Double_t *x, Double_t *par) {
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 Double_t y = x[0];
01216 Double_t w = par[0];
01217 Double_t h = par[1];
01218 Double_t K3 = par[3];
01219 Double_t lambda = y/h;
01220 Double_t K2 = TMath::PiOver2()*(1. - 0.5*TMath::Sqrt(K3));
01221
01222 Double_t sqK3 = TMath::Sqrt(K3);
01223 Double_t ATsqK3 = 0.5/TMath::ATan(sqK3);
01224 Double_t Y1 = lambda - w/h/2;
01225 Double_t Y2 = Y1 + w/h;
01226 Double_t X1 = K2*Y1;
01227 Double_t X2 = K2*Y2;
01228 Double_t Z1 = sqK3*TMath::TanH(X1);
01229 Double_t Z2 = sqK3*TMath::TanH(X2);
01230 Double_t val = ATsqK3*(TMath::ATan(Z2) - TMath::ATan(Z1));
01231 return val;
01232 }
01233
01234 void StTpcRSMaker::Print(Option_t *) const {
01235 PrPP(Print, NoOfSectors);
01236 PrPP(Print, NoOfRows);
01237 PrPP(Print, NoOfInnerRows);
01238 PrPP(Print, NoOfPads);
01239 PrPP(Print, St_TpcResponseSimulatorC::instance()->W());
01240 PrPP(Print, St_TpcResponseSimulatorC::instance()->Cluster());
01241 PrPP(Print, St_TpcResponseSimulatorC::instance()->longitudinalDiffusion());
01242 PrPP(Print, St_TpcResponseSimulatorC::instance()->transverseDiffusion());
01243
01244 PrPP(Print, NoOfTimeBins);
01245 PrPP(Print, numberOfInnerSectorAnodeWires);
01246 PrPP(Print, firstInnerSectorAnodeWire);
01247 PrPP(Print, lastInnerSectorAnodeWire);
01248 PrPP(Print, numberOfOuterSectorAnodeWires);
01249 PrPP(Print, firstOuterSectorAnodeWire);
01250 PrPP(Print, lastOuterSectorAnodeWire);
01251 PrPP(Print, anodeWirePitch);
01252 PrPP(Print,St_TpcResponseSimulatorC::instance()->OmegaTau());
01253 PrPP(Print, St_TpcResponseSimulatorC::instance()->NoElPerAdc());
01254 PrPP(Print, anodeWireRadius);
01255 PrPP(Print, St_TpcResponseSimulatorC::instance()->AveragePedestal());
01256 PrPP(Print, St_TpcResponseSimulatorC::instance()->AveragePedestalRMS());
01257 PrPP(Print, St_TpcResponseSimulatorC::instance()->AveragePedestalRMSX());
01258 PrPP(Print, St_TpcResponseSimulatorC::instance()->FanoFactor());
01259 PrPP(Print, innerSectorAnodeVoltage);
01260 PrPP(Print, outerSectorAnodeVoltage);
01261 PrPP(Print, St_TpcResponseSimulatorC::instance()->K3IP());
01262 PrPP(Print, St_TpcResponseSimulatorC::instance()->K3IR());
01263 PrPP(Print, St_TpcResponseSimulatorC::instance()->K3OP());
01264 PrPP(Print, St_TpcResponseSimulatorC::instance()->K3OR());
01265 PrPP(Print, St_TpcResponseSimulatorC::instance()->SigmaJitterTI());
01266 PrPP(Print, St_TpcResponseSimulatorC::instance()->SigmaJitterTO());
01267 }
01268
01269 void StTpcRSMaker::DigitizeSector(Int_t sector){
01270
01271 TDataSet *event = GetData("Event");
01272 StTpcRawData *data = 0;
01273 if (! event) {
01274 data = new StTpcRawData(NoOfSectors);
01275 event = new TObjectSet("Event", data);
01276 AddData(event);
01277 } else data = (StTpcRawData *) event->GetObject();
01278 assert(data);
01279 SignalSum_t *SignalSum = GetSignalSum();
01280 Double_t ped = 0;
01281 Double_t pedRMS = St_TpcResponseSimulatorC::instance()->AveragePedestalRMS();
01282 Int_t itpc = 0;
01283 if (St_tpcAltroParamsC::instance()->N(sector-1) >= 0) {
01284 pedRMS = St_TpcResponseSimulatorC::instance()->AveragePedestalRMSX();
01285 itpc = 1;
01286 }
01287 Int_t adc = 0;
01288 Int_t index = 0;
01289 Double_t gain = 1;
01290 Int_t row, pad, bin;
01291 Int_t Sector = TMath::Abs(sector);
01292 StTpcDigitalSector *digitalSector = data->GetSector(Sector);
01293 if (! digitalSector) {
01294 digitalSector = new StTpcDigitalSector();
01295 data->setSector(Sector,digitalSector);
01296 } else
01297 digitalSector->clear();
01298 for (row = 1; row <= NoOfRows; row++) {
01299 Int_t NoOfPadsAtRow = St_tpcPadPlanesC::instance()->padsPerRow(row);
01300 Int_t io = 0;
01301 if (row > NoOfInnerRows) io = 1;
01302 for (pad = 1; pad <= NoOfPadsAtRow; pad++) {
01303 gain = St_tpcPadGainT0C::instance()->Gain(Sector,row,pad);
01304 if (gain <= 0.0) continue;
01305 ped = St_TpcResponseSimulatorC::instance()->AveragePedestal();
01306 static Short_t ADCs[__MaxNumberOfTimeBins__];
01307 static UShort_t IDTs[__MaxNumberOfTimeBins__];
01308 memset(ADCs, 0, sizeof(ADCs));
01309 memset(IDTs, 0, sizeof(IDTs));
01310 Int_t NoTB = 0;
01311 index = NoOfTimeBins*((row-1)*NoOfPads+pad-1);
01312 for (bin = 0; bin < NoOfTimeBins; bin++,index++) {
01313
01314
01315
01316 Double_t pRMS = pedRMS;
01317 #if 0
01318 if (bin >= 21 && bin <= 56) {
01319 pRMS = TMath::Sqrt(pedRMS*pedRMS + 4.76658e+01*TMath::Exp(-2.87987e-01*(bin-1.46222e+01)));
01320 }
01321 #endif
01322 if (pRMS > 0) {
01323 adc = (Int_t) (SignalSum[index].Sum/gain + gRandom->Gaus(ped,pRMS));
01324 adc = adc - (Int_t) ped;
01325 }
01326 else adc = (Int_t) (SignalSum[index].Sum/gain);
01327 if (adc > 1023) adc = 1023;
01328 if (adc < 1) continue;
01329 SignalSum[index].Adc = adc;
01330 NoTB++;
01331 ADCs[bin] = adc;
01332 IDTs[bin] = SignalSum[index].TrackId;
01333 #if 1
01334 if (Debug()%10 > 2 && SignalSum[index].Sum > 0) {
01335 LOG_INFO << "digi R/P/T/I = " << row << " /\t" << pad << " /\t" << bin << " /\t" << index
01336 << "\tSum/Adc/TrackId = " << SignalSum[index].Sum << " /\t"
01337 << SignalSum[index].Adc << " /\t" << SignalSum[index].TrackId << endm;
01338 }
01339 #endif
01340 }
01341 if (! NoTB) continue;
01342 if (St_tpcAltroParamsC::instance()->N(sector-1) >= 0 && ! mAltro) {
01343 mAltro = new Altro(__MaxNumberOfTimeBins__,ADCs);
01344 if (St_tpcAltroParamsC::instance()->N(sector-1) > 0) {
01345
01346 mAltro->ConfigAltro( 0, 1, 0, 1, 1);
01347
01348
01349 mAltro->ConfigTailCancellationFilter(St_tpcAltroParamsC::instance()->K1(),
01350 St_tpcAltroParamsC::instance()->K2(),
01351 St_tpcAltroParamsC::instance()->K3(),
01352 St_tpcAltroParamsC::instance()->L1(),
01353 St_tpcAltroParamsC::instance()->L2(),
01354 St_tpcAltroParamsC::instance()->L3());
01355 } else {
01356 mAltro->ConfigAltro(0,0,0,1,1);
01357 }
01358 mAltro->ConfigZerosuppression(St_tpcAltroParamsC::instance()->Threshold(),
01359 St_tpcAltroParamsC::instance()->MinSamplesaboveThreshold(),
01360 0,0);
01361 mAltro->PrintParameters();
01362 }
01363 if (mAltro) {
01364
01365 #ifdef PixelDUMP
01366 static Short_t ADCsSaved[__MaxNumberOfTimeBins__];
01367 memcpy(ADCsSaved, ADCs,sizeof(ADCsSaved));
01368 #endif
01369 mAltro->RunEmulation();
01370 #ifdef PixelDUMP
01371 ofstream *out = new ofstream("digi.dump",ios_base::app);
01372 for (Int_t i = 0; i < __MaxNumberOfTimeBins__; i++) {
01373 if (ADCsSaved[i] > 0 || ADCs[i] > 0) {
01374 LOG_INFO << Form("s %2i r %i p %3i t %3i: %10i => %10i keep %10i",sector,row,pad,i,ADCsSaved[i],ADCs[i],mAltro->ADCkeep[i]) << endm;
01375 *out << Form("s %2i r %i p %3i t %3i: %10i => %10i keep %10i",sector,row,pad,i,ADCsSaved[i],ADCs[i],mAltro->ADCkeep[i]) << endl;
01376 }
01377 }
01378 delete out;
01379 #endif
01380 for (Int_t i = 0; i < __MaxNumberOfTimeBins__; i++) {
01381 if (ADCs[i] && ! mAltro->ADCkeep[i]) {ADCs[i] = 0; NoTB--;}
01382 }
01383 }
01384 else {
01385 if (St_tpcAltroParamsC::instance()->N(sector-1) < 0) NoTB = AsicThresholds(ADCs);
01386 }
01387 if (NoTB > 0 && digitalSector) {
01388 digitalSector->putTimeAdc(row,pad,ADCs,IDTs);
01389 }
01390 }
01391 }
01392 }
01393
01394 Int_t StTpcRSMaker::AsicThresholds(Short_t ADCs[__MaxNumberOfTimeBins__]) {
01395 Int_t t1 = 0;
01396 Int_t nSeqLo = 0;
01397 Int_t nSeqHi = 0;
01398 Int_t noTbleft = 0;
01399 for (UInt_t tb = 0; tb < __MaxNumberOfTimeBins__; tb++) {
01400 if (ADCs[tb] <= St_asic_thresholdsC::instance()->thresh_lo()) {
01401 if (! t1) ADCs[tb] = 0;
01402 else {
01403 if (nSeqLo <= St_asic_thresholdsC::instance()->n_seq_lo() ||
01404 nSeqHi <= St_asic_thresholdsC::instance()->n_seq_hi())
01405 for (UInt_t t = t1; t <= tb; t++) ADCs[t] = 0;
01406 else noTbleft += nSeqLo;
01407 }
01408 t1 = nSeqLo = nSeqHi = 0;
01409 }
01410 nSeqLo++;
01411 if (! t1) t1 = tb;
01412 if (ADCs[tb] > St_asic_thresholdsC::instance()->thresh_hi()) {nSeqHi++;}
01413 }
01414 return noTbleft;
01415 }
01416
01417 Double_t StTpcRSMaker::InducedCharge(Double_t s, Double_t h, Double_t ra, Double_t Va, Double_t &t0) {
01418
01419
01420 LOG_INFO << "wire spacing = " << s << " cm"
01421 << "\tcathode anode gap = " << h << " cm"
01422 << "\tanode wire radius = " << ra << " cm"
01423 << "\tpotential on anode wire = " << Va << " V" << endm;
01424 const Double_t B = 30e-3;
01425 const Double_t E0 = 20e3;
01426 const Double_t mu = 2.26;
01427
01428 Double_t alpha[2] = {-26., -70.};
01429 Double_t pi = TMath::Pi();
01430
01431 Double_t rc = s/(2*pi)*TMath::Exp(pi*h/s); LOG_INFO << "rc(Cylinder approx) = " << rc << " cm" << endm;
01432
01433 Double_t C = 1./(2*TMath::Log(rc/ra)); LOG_INFO << "C = " << C << endm;
01434 Double_t E = 2*pi*C*Va/s; LOG_INFO << "E = " << E << " V/cm" << endm;
01435
01436 Double_t k = 2*B/3.*TMath::Power((pi/E0/s),2)*TMath::Power(C*Va,3); LOG_INFO << "k = " << k << endm;
01437
01438 t0 = ra*ra/(4*mu*C*Va);
01439 LOG_INFO << "t0 = " << 1e9*t0 << " ns" << endm;
01440 Double_t Tav = t0*h/s/(2*pi*C); LOG_INFO << "Tav = " << 1e9*Tav << " ns" << endm;
01441
01442 Double_t t = 180e-9; LOG_INFO << "t = " << 1e9*t << " ns" << endm;
01443 Double_t rp = TMath::Sqrt(1. + t/t0); LOG_INFO << "r' = " << rp << endm;
01444
01445 Double_t Aconstant = rp*ra/(2*h); LOG_INFO << "Aconstant = " << Aconstant << endm;
01446 Double_t Bconstant = C/2*TMath::Log(1 + t/t0); LOG_INFO << "Bconstant = " << Bconstant << endm;
01447 Double_t Gains[2];
01448 for (Int_t i = 0; i < 2; i++) {
01449 Gains[i] = Aconstant*TMath::Sin(pi/180*alpha[i]) + Bconstant;
01450 LOG_INFO << "Gain = " << Gains[i] << " at alpha = " << alpha[i] << " degree" << endm;
01451 }
01452 Double_t GainsAv = TMath::Sqrt(Gains[0]*Gains[1]);
01453 Double_t r = 0;
01454 for (Int_t i = 0; i < 2; i++) {
01455 r = TMath::Log(Gains[i]/GainsAv); LOG_INFO << "Relative gain " << r << " at alpha = " << alpha[i] << endm;
01456 }
01457 return r;
01458 }
01459
01460 Int_t StTpcRSMaker::SearchT(const void *elem1, const void **elem2) {
01461 g2t_tpc_hit_st *value1 = (g2t_tpc_hit_st *) elem1;
01462 g2t_tpc_hit_st *value2 = (g2t_tpc_hit_st *) *elem2;
01463
01464 if ((value1->volume_id%100000)/100 != (value2->volume_id%100000)/100)
01465 return (value1->volume_id%100000)/100 - (value2->volume_id%100000)/100;
01466
01467 if (value1->track_p != value2->track_p) return value1->track_p - value2->track_p;
01468
01469
01470
01471 return (Int_t) 100*(value1->length - value2->length);
01472 }
01473
01474 Int_t StTpcRSMaker::CompareT(const void **elem1, const void **elem2) {
01475 return SearchT(*elem1, elem2);
01476 }
01477 #if 0
01478
01479 Double_t StTpcRSMaker::DriftLength(Double_t x, Double_t y) {
01480 static const Double_t Step = 5e-2;
01481 Double_t r = TMath::Sqrt(x*x + y*y);
01482 if (r < 0.25) return r;
01483 x = TMath::Abs(x);
01484 y = TMath::Abs(y);
01485 Int_t Nstep = 0;
01486 while (x > Step || y > Step) {
01487 Double_t Slope = TMath:SinH(TMath::Pi()*y/s)/TMath:Sin(TMath::Pi()*x/s);
01488 Double_t Co2 = 1./(1. + Slope*Slope);
01489 Double_t Si = TMath::Sqrt(1. - Co2);
01490 Double_t Co = TMath::Sqrt(Co2);
01491 x = TMath::Abs(x - Step*Co);
01492 y = TMath::Abs(y - Step*Si);
01493 NStep++
01494 }
01495 return NStep*Step;
01496 }
01497 #endif
01498
01499 Double_t StTpcRSMaker::fei(Double_t t, Double_t t0, Double_t T) {
01500 static const Double_t xmaxt = 708.39641853226408;
01501 static const Double_t xmaxD = xmaxt - TMath::Log(xmaxt);
01502 Double_t t01 = xmaxD, t11 = xmaxD;
01503 if (T > 0) {t11 = (t+t0)/T;}
01504 if (t11 > xmaxD) t11 = xmaxD;
01505 if (T > 0) {t01 = t0/T;}
01506 if (t01 > xmaxD) t01 = xmaxD;
01507 return TMath::Exp(-t11)*(ROOT::Math::expint(t11) - ROOT::Math::expint(t01));
01508 }
01509
01510 Double_t StTpcRSMaker::shapeEI(Double_t *x, Double_t *par) {
01511 Double_t t = x[0];
01512 Double_t value = 0;
01513 if (t <= 0) return value;
01514 Double_t t0 = par[0];
01515 Double_t T1 = par[1];
01516 Double_t T2 = par[3];
01517 if (TMath::Abs((T1-T2)/(T1+T2)) < 1e-7) {
01518 return TMath::Max(0.,(t + t0)/T1*fei(t,t0,T1) + TMath::Exp(-t/T1) - 1);
01519 }
01520 if (T2 <= 0) return fei(t,t0,T1);
01521 if (T1 <= 0) return 0;
01522 return T1/(T1 - T2)*(fei(t,t0,T1) - fei(t,t0,T2));
01523 }
01524
01525 Double_t StTpcRSMaker::shapeEI3(Double_t *x, Double_t *par) {
01526 Double_t t = x[0];
01527 Double_t value = 0;
01528 if (t <= 0) return value;
01529 Double_t t0 = par[0];
01530 Double_t tau_F = par[1];
01531 Double_t tau_P = par[2];
01532 Double_t tau_I = par[3];
01533 Double_t tau_C = par[5];
01534 Double_t d = 1./tau_P;
01535 Double_t a[3] = {- 1./tau_I, - 1./tau_F, 0};
01536 Double_t A[3] = {(a[0]+d)/(a[0]-a[1]), (a[1]+d)/(a[1]-a[0]), 0};
01537 Int_t N = 2;
01538 if (tau_C > 0) {
01539 N = 3;
01540 a[2] = -1./tau_C;
01541 A[0] = (a[0] + d)/a[0]/(a[0] - a[1])/(a[0] - a[2]);
01542 A[1] = (a[1] + d)/a[1]/(a[1] - a[0])/(a[1] - a[2]);
01543 A[2] = (a[2] + d)/a[2]/(a[2] - a[0])/(a[2] - a[1]);
01544 }
01545 for (Int_t i = 0; i < N; i++) {
01546 value += A[i]*TMath::Exp(a[i]*(t+t0))*(ROOT::Math::expint(-a[i]*(t+t0))-ROOT::Math::expint(-a[i]*t0));
01547 }
01548 return value;
01549 }
01550
01551 Double_t StTpcRSMaker::shapeEI_I(Double_t *x, Double_t *par) {
01552 static Double_t sqrt2 = TMath::Sqrt(2.);
01553 Double_t TimeBinWidth = par[2];
01554 Double_t norm = par[3];
01555 Double_t t1 = TimeBinWidth*(x[0] - 0.5);
01556 Double_t t2 = t1 + TimeBinWidth;
01557 Int_t io = (Int_t) par[4];
01558 assert(io >= 0 && io <= 1);
01559 return sqrt2*fgTimeShape0[io]->Integral(t1,t2)/norm;
01560 }
01561
01562 Double_t StTpcRSMaker::shapeEI3_I(Double_t *x, Double_t *par) {
01563 static Double_t sqrt2 = TMath::Sqrt(2.);
01564 Double_t TimeBinWidth = par[4];
01565 Double_t norm = par[5];
01566 Double_t t1 = TimeBinWidth*(x[0] - 0.5);
01567 Double_t t2 = t1 + TimeBinWidth;
01568 Int_t io = (Int_t) par[6];
01569 assert(io >= 0 && io <= 1);
01570 return sqrt2*fgTimeShape3[io]->Integral(t1,t2)/norm;
01571 }
01572
01573 SignalSum_t *StTpcRSMaker::GetSignalSum() {
01574 if (! m_SignalSum)
01575 m_SignalSum = (SignalSum_t *) malloc(NoOfRows*NoOfPads*NoOfTimeBins*sizeof(SignalSum_t));
01576 return m_SignalSum;
01577 }
01578
01579 SignalSum_t *StTpcRSMaker::ResetSignalSum() {
01580 GetSignalSum();
01581 memset (m_SignalSum, 0, NoOfRows*NoOfPads*NoOfTimeBins*sizeof(SignalSum_t));
01582 return m_SignalSum;
01583 }
01584
01585 Double_t StTpcRSMaker::polya(Double_t *x, Double_t *par) {
01586 return TMath::GammaDist(x[0],par[0],par[1],par[2]);
01587 }
01588
01589 Double_t StTpcRSMaker::Ec(Double_t *x, Double_t *p) {
01590 if (x[0] < p[0]/2 || x[0] > 3.064*p[0]) return 0;
01591 if (x[0] < p[0]) return 1;
01592 return TMath::Power(p[0]/x[0],4);
01593 }
01594
01595 TF1 *StTpcRSMaker::StTpcRSMaker::fEc(Double_t w) {
01596 TF1 *f = new TF1("Ec",Ec,0,3.064*w,1);
01597 f->SetParameter(0,w);
01598 return f;
01599 }
01600
01601 #undef PrPP
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829