8 #include "StSpaceChargeDistMaker.h"
11 #include "StEventTypes.h"
12 #include "StDetectorDbMaker/St_tpcPadGainT0BC.h"
13 #include "StDetectorDbMaker/St_tss_tssparC.h"
14 #include "StDetectorDbMaker/StDetectorDbTpcRDOMasks.h"
15 #include "StDetectorDbMaker/St_tpcPadConfigC.h"
16 #include "StDetectorDbMaker/St_TpcSecRowBC.h"
17 #include "StDetectorDbMaker/St_TpcAvgCurrentC.h"
18 #include "StDbUtilities/StMagUtilities.h"
19 #include "StDbUtilities/StTpcCoordinateTransform.hh"
20 #include "StdEdxY2Maker/StTpcdEdxCorrection.h"
30 static const Int_t nz = 105;
31 static const Double_t zmin = -205;
32 static const Double_t zmax = 205;
33 static const Int_t nr = 17;
34 static const Double_t rmin = 40.;
35 static const Double_t rmax = 210;
36 static const Int_t nph = 12;
37 static const Double_t phmin = -TMath::Pi();
38 static const Double_t phmax = TMath::Pi();
39 static const Double_t PhiMax = TMath::Pi()/12;
40 static const Int_t nrph = nr*nph;
41 static const Double_t ZdcMax = 2e6;
43 static const Double_t MINGAIN = 0.1;
45 static TMatrixD* RPMats[nz];
46 static TMatrixD* RMats[nz];
47 static TVectorD* RPMatHs[nz];
48 static TVectorD* RMatHs[nz];
54 event(0), Space3ChargePRZ(0), Space3ChargeU(0),
55 thrownR(0), acceptedR(0),
56 thrownRP(0), acceptedRP(0),
57 thrownP(0), acceptedP(0),
60 GGZ = 0; NP = 0; NR = 0; NS = 0;
63 memset(Xpads,0,128*
sizeof(Float_t));
64 memset(Npads,0,128*
sizeof(UShort_t));
65 memset(XMIN,0,128*
sizeof(Float_t));
66 memset(YMIN,0,32768*
sizeof(Float_t));
67 memset(LiveRow,0,4096*
sizeof(Bool_t));
68 memset(LivePad,0,1048576*
sizeof(Bool_t));
71 StSpaceChargeDistMaker::~StSpaceChargeDistMaker() {
74 void StSpaceChargeDistMaker::AcceptTrigger(Int_t trig) {
75 Int_t ntrig = trigs.GetSize();
77 LOG_INFO <<
"StSpaceChargeDistMaker: Accepting all triggers." << endm;
79 LOG_INFO <<
"StSpaceChargeDistMaker: Accepting trigger (" << ntrig <<
") : " << trig << endm;
82 trigs.AddAt(trig,ntrig);
87 TH2D *rGeom =
new TH2D(*acceptedR);
88 rGeom->SetName(
"rGeom");
89 rGeom->Divide(thrownR);
90 TH2D *phGeom =
new TH2D(*acceptedP);
91 phGeom->SetName(
"phGeom");
92 phGeom->Divide(thrownP);
93 TH3D *rpGeom =
new TH3D(*acceptedRP);
94 rpGeom->SetName(
"rpGeom");
95 rpGeom->Divide(thrownRP);
97 TH3D* S3CPRZ =
new TH3D(*Space3ChargePRZ);
98 S3CPRZ->SetName(Form(
"%sOrig",Space3ChargePRZ->GetName()));
99 TH3D* S3CU =
new TH3D(*Space3ChargeU);
100 S3CU->SetName(Form(
"%sOrig",Space3ChargeU->GetName()));
102 TFile* ff =
new TFile(Form(
"SCdist_%d.root",run),
"RECREATE");
113 LOG_INFO <<
"StSpaceChargeDistMaker: attempting to de-smear..." << endm;
114 for (Int_t zbin=1; zbin<=nz; zbin++) {
116 Int_t bingen,binfnd,desmearing_mode = -1;
120 TMatrixD& MatM = *(RPMats[zbin-1]);
121 TVectorD& MatH = *(RPMatHs[zbin-1]);
122 for (bingen=0; bingen<nrph; bingen++) {
123 denom = MatH[bingen];
124 for (binfnd=0; binfnd<nrph; binfnd++) {
125 if (denom > 0) MatM[binfnd][bingen] /= denom;
126 else if (binfnd==bingen) MatM[binfnd][bingen] = 1.0;
131 MatM.Write(Form(
"RPMat%03d",zbin));
132 MatH.Write(Form(
"RPMatH%03d",zbin));
139 MatM = *(RMats[zbin-1]);
140 MatH = *(RMatHs[zbin-1]);
141 for (bingen=0; bingen<nr; bingen++) {
142 denom = MatH[bingen];
143 for (binfnd=0; binfnd<nr; binfnd++) {
144 if (denom > 0) MatM[binfnd][bingen] /= denom;
145 else if (binfnd==bingen) MatM[binfnd][bingen] = 1.0;
150 MatM.Write(Form(
"RMat%03d",zbin));
151 MatH.Write(Form(
"RMatH%03d",zbin));
155 LOG_INFO <<
"StSpaceChargeDistMaker: z bin " << zbin
156 <<
" will use r matrices instead of r-phi" << endm;
159 LOG_WARN <<
"StSpaceChargeDistMaker: z bin " << zbin
160 <<
" could not invert matrices, giving up!" << endm;
166 if (desmearing_mode > 0) {
167 Double_t newcontPRZ, newcontU, coef;
168 for (Int_t rbin=1; rbin<=nr; rbin++) {
169 for (Int_t phibin=1; phibin<=nph; phibin++) {
170 bingen = (rbin-1) + (desmearing_mode == 2 ? nr*(phibin-1) : 0);
173 for (Int_t rbin2=1; rbin2<=nr; rbin2++) {
174 for (Int_t phibin2=1; phibin2<=nph; phibin2++) {
175 if (desmearing_mode == 1 && phibin2 != phibin)
continue;
176 binfnd = (rbin2-1) + (desmearing_mode == 2 ? nr*(phibin2-1) : 0);
177 coef = MatM[bingen][binfnd];
178 if (TMath::IsNaN(coef)) {
179 LOG_ERROR <<
"StSpaceChargeDistMaker: de-smearing matrix element ["
180 << bingen <<
"][" << binfnd <<
"] (zbin=" << zbin <<
") is NaN !"
183 newcontPRZ += coef * S3CPRZ->GetBinContent(phibin2,rbin2,zbin);
184 newcontU += coef * S3CU ->GetBinContent(phibin2,rbin2,zbin);
188 Space3ChargePRZ->SetBinContent(phibin,rbin,zbin,newcontPRZ);
189 Space3ChargeU ->SetBinContent(phibin,rbin,zbin,newcontU );
197 Space3ChargePRZ->Write();
198 Space3ChargeU->Write();
202 delete Space3ChargePRZ;
203 delete Space3ChargeU;
208 Int_t StSpaceChargeDistMaker::InitRun(Int_t run) {
209 if (thrownR->GetEntries() < 1) GeomInit();
213 Int_t StSpaceChargeDistMaker::Init() {
214 Space3ChargePRZ =
new TH3D(
"Space3ChargePRZ",
"Space charged versus Phi(rads), Rho and Z",
215 nph,phmin,phmax,nr,rmin,rmax,nz,zmin,zmax);
216 Space3ChargeU =
new TH3D(
"Space3ChargeU" ,
"Space charged versus Phi(rads), Rho and Z (on tracks)",
217 nph,phmin,phmax,nr,rmin,rmax,nz,zmin,zmax);
218 Space3ChargePRZ->Sumw2();
219 Space3ChargeU->Sumw2();
220 thrownR =
new TH2D(
"R",
"r",nr,rmin,rmax,3,-1.5,1.5);
221 acceptedR =
new TH2D(
"P",
"pads",nr,rmin,rmax,3,-1.5,1.5);
222 thrownRP =
new TH3D(
"RP",
"rp",nr,rmin,rmax,nph,phmin,phmax,3,-1.5,1.5);
223 acceptedRP =
new TH3D(
"RPP",
"pads rp",nr,rmin,rmax,nph,phmin,phmax,3,-1.5,1.5);
224 thrownP =
new TH2D(
"PH",
"phi",nph,phmin,phmax,3,-1.5,1.5);
225 acceptedP =
new TH2D(
"PP",
"pads phi",nph,phmin,phmax,3,-1.5,1.5);
226 ZdcC =
new TH1D(
"ZdcC",
"ZDC coincidence rate",1024,0,ZdcMax);
228 for (
int i=0;i<nz;i++) {
229 RPMats[i] =
new TMatrixD(nrph,nrph);
230 RPMatHs[i] =
new TVectorD(nrph);
231 RMats[i] =
new TMatrixD(nr,nr);
232 RMatHs[i] =
new TVectorD(nr);
233 RPMats[i]->SetTol(1e-6);
234 RMats[i]->SetTol(1e-6);
237 return StMaker::Init();
242 if (trigs.GetSize() < 1) {
243 LOG_ERROR <<
"StSpaceChargeDistMaker: NO ACCEPTABLE TRIGGERS DEFINED!" << endm;
248 event =
static_cast<StEvent*
>(GetInputDS(
"StEvent"));
250 LOG_WARN <<
"StSpaceChargeDistMaker: no StEvent; skipping event." << endm;
255 if (trigs.At(0) >= 0) {
256 Bool_t passTrigs = kFALSE;
257 if (event->triggerIdCollection() &&
258 event->triggerIdCollection()->nominal()) {
259 for (Int_t i=0; (!passTrigs) && (i<trigs.GetSize()); i++) {
260 passTrigs =
event->triggerIdCollection()->nominal()->isTrigger(trigs.At(i));
262 if (!passTrigs) { LOG_WARN <<
"StSpaceChargeDistMaker: Triggers not accepted" << endm; }
263 }
else { LOG_WARN <<
"StSpaceChargeDistMaker: Could not find nominal trigger id collection" << endm; }
264 if (!passTrigs)
return kStOK;
268 LOG_ERROR <<
"StSpaceChargeDistMaker: no gStTpcDb - should quit!" << endm;
276 static Int_t number_dedx_faults = 0;
277 static Int_t warn_dedx_faults = 1;
279 if (!m_TpcdEdxCorrection) {
282 CLRBIT(Mask,StTpcdEdxCorrection::kdXCorrection);
285 if (!m_TpcdEdxCorrection) {
286 LOG_ERROR <<
"StSpaceChargeDistMaker: no dE/dx corrections - should quit!" << endm;
292 if (TpcHitCollection) {
293 Double_t zdcc =
event->runInfo()->zdcCoincidenceRate();
296 LOG_WARN <<
"StSpaceChargeDistMaker: ZDC rate greater than hist max ( "
297 << zdcc <<
" > " << ZdcMax <<
" )" << endm;
299 if (!run) run =
event->runId();
301 UInt_t numberOfSectors = TpcHitCollection->numberOfSectors();
302 for (UInt_t i = 0; i< numberOfSectors; i++) {
304 if (sectorCollection) {
305 Int_t numberOfPadrows = sectorCollection->numberOfPadrows();
306 for (Int_t j = 0; j< numberOfPadrows; j++) {
307 if (! LiveRow[j + NP*i])
continue;
310 UInt_t NoHits = rowCollection->hits().size();
311 for (UInt_t k = 0; k < NoHits; k++) {
312 StTpcHit* tpcHit = TpcHitCollection->sector(i)->padrow(j)->hits().at(k);
316 if (TMath::Abs(positionG.z()) > 200)
continue;
319 if (tpcHit->pad() < 5 || tpcHit->pad() > Npads[j]-4)
continue;
322 Float_t charge = tpcHit->charge();
323 if (charge <= 0)
continue;
328 transform(coorG,coorLT,i+1,j+1);
333 if (positionL.z() * (((Float_t) i)-11.5) > 0)
continue;
334 if (TMath::Abs(positionL.z()) > 180)
continue;
337 memset(&CdEdx, 0,
sizeof(
dEdxY2_t));
344 Double_t Qcm = St_TpcAvgCurrentC::instance()->AcChargeRowL(CdEdx.sector,CdEdx.row);
345 CdEdx.pad = tpcHit->pad();
346 CdEdx.edge = CdEdx.pad;
347 if (CdEdx.edge > 0.5*Npads[j])
348 CdEdx.edge += 1 - Npads[j];
350 CdEdx.adc = tpcHit->adc();
351 CdEdx.F.dx = XWID[j];
352 CdEdx.xyz[0] = positionL.x();
353 CdEdx.xyz[1] = positionL.y();
354 CdEdx.xyz[2] = positionL.z();
355 Double_t probablePad = ((Double_t) Npads[j])/2.;
356 Double_t pitch = St_tpcPadConfigC::instance()->PadPitchAtRow(CdEdx.sector,CdEdx.row);
357 Double_t PhiMax = TMath::ATan2(probablePad*pitch, Xpads[j]);
358 CdEdx.PhiR = TMath::ATan2(CdEdx.xyz[0],CdEdx.xyz[1])/PhiMax;
360 CdEdx.zG = CdEdx.xyz[2];
362 CdEdx.Crow = St_TpcAvgCurrentC::instance()->AvCurrRow(CdEdx.sector,CdEdx.row);
368 CdEdx.ZdriftDistance = 104.3535;
369 St_tpcGas *tpcGas = m_TpcdEdxCorrection->tpcGas();
371 CdEdx.ZdriftDistanceO2 = CdEdx.ZdriftDistance*(*tpcGas)[0].ppmOxygenIn;
372 Int_t dedx_status = m_TpcdEdxCorrection->dEdxCorrection(CdEdx);
374 number_dedx_faults++;
375 if (number_dedx_faults == warn_dedx_faults) {
376 LOG_WARN <<
"StSpaceChargeDistMaker: found at least " <<
377 number_dedx_faults <<
" dE/dx fault(s), code: " << dedx_status << endm;
378 warn_dedx_faults *= 10;
381 LOG_WARN << Form(
"FAULT: %d %d %d %g %d %g %g %g %g %g\n",dedx_status,
382 i+1,j+1,tpcHit->pad(),Npads[j],
383 positionL.x(),positionL.y(),positionL.z(),
384 charge,CdEdx.F.dE) << endm;
390 Space3ChargePRZ->Fill(positionL.phi(),
394 if (tpcHit->trackReferenceCount() > 0)
395 Space3ChargeU ->Fill(positionL.phi(),
399 for (Double_t throwi =
throws; throwi>0; throwi--)
400 if (throwi>=1 || ((Int_t) (gRandom->Rndm()/throwi))==0)
401 GeomFill(positionL.z());
411 void StSpaceChargeDistMaker::GeomInit() {
415 GGZ = St_tpcDimensionsC::instance()->gatingGridZ();
416 NP = St_tpcPadConfigC::instance()->padRows(20);
439 Int_t i,j,k,l,m,isec,irow,ipad;
441 LOG_INFO <<
"StSpaceChargeDistMaker: Now reading live/dead/gains for acceptance" << endm;
442 for (i = 0; i < 24; i++) {
444 Float_t* gainScales = St_TpcSecRowBC::instance()->GainScale(i);
445 for (j = 0; j < NP; j++) {
447 pitch = St_tpcPadConfigC::instance()->PadPitchAtRow(20,irow);
449 Npads[j] = St_tpcPadConfigC::instance()->padsPerRow(20,irow);
450 Xpads[j] = St_tpcPadConfigC::instance()->radialDistanceAtRow(20,irow);
451 XWID[j] = St_tpcPadConfigC::instance()->PadLengthAtRow(20,irow);
452 XMIN[j] = Xpads[j] - 0.5*XWID[j];
455 LiveRow[m] = (StDetectorDbTpcRDOMasks::instance()->isOn(isec,
456 StDetectorDbTpcRDOMasks::instance()->rdoForPadrow(isec,irow)) &&
457 (St_tss_tssparC::instance()->gain(isec,irow) > 0) &&
460 for (k=0; k<Npads[j]; k++) {
463 LivePad[l] = (LiveRow[m] &&
464 k>3 && k<Npads[j]-4 &&
465 St_tpcPadGainT0BC::instance()->Gain(isec,irow,ipad) > MINGAIN);
466 if (i==0) YMIN[l] = pitch * (k - 0.5*Npads[j]);
470 LOG_INFO <<
"StSpaceChargeDistMaker: will throw approximately 12*" <<
throws <<
" hits per TPC hit." << endm;
474 void StSpaceChargeDistMaker::GeomFill(Float_t z) {
483 Float_t phi0,phi,phi2,phi3,phi4,r,r2,r4,x,y,zbin,zpileup;
488 Int_t rbin,phibin,tempbin,bingen,binfnd,bingenR,binfndR;
494 static const Double_t rdist0 = -1.71 + 1.0;
497 static const Double_t rdist1 = TMath::Power(49,rdist0);
498 static const Double_t rdist2 = TMath::Power(rmax,rdist0) - rdist1;
499 static const Double_t rdist3 = 1.0/rdist0;
501 while (i < 12*TMath::Max(1,(Int_t)
throws)) {
506 r = TMath::Power(rdist1 + rdist2*gRandom->Rndm(),rdist3);
508 phi0 = PhiMax*(2*gRandom->Rndm() - 1);
509 j = (Int_t) (12*gRandom->Rndm());
510 zpileup = GGZ*gRandom->Rndm();
515 phi = phi0 - (k-2)*TMath::Pi()/6.0;
519 phi = -phi0 + (k-20)*TMath::Pi()/6.0;
522 while (phi>=phmax) phi -= TMath::TwoPi();
523 while (phi< phmin) phi += TMath::TwoPi();
525 thrownRP->Fill(r,phi,0);
526 thrownP->Fill(phi,0);
527 thrownR->Fill(r,zbin);
528 thrownRP->Fill(r,phi,zbin);
529 thrownP->Fill(phi,zbin);
532 pos1[0] = r*TMath::Cos(phi);
533 pos1[1] = r*TMath::Sin(phi);
536 phi2 = TMath::ATan2(pos2[1],pos2[0]);
537 r2 = TMath::Sqrt(pos2[0]*pos2[0]+pos2[1]*pos2[1]);
541 phi3 = phi0 + ((phi2-phi)*(pos2[2] < 0 ? -1.0 : 1.0));
542 x = r2*TMath::Cos(phi3);
543 y = r2*TMath::Sin(phi3);
546 ix = (Int_t) (TMath::BinarySearch(NP,&XMIN[0],x));
547 if (ix < 0 || ix >= NP)
continue;
548 pitch = St_tpcPadConfigC::instance()->PadPitchAtRow(20,ix+1);
549 if (x > XMIN[ix] + XWID[ix])
continue;
550 iy = (Int_t) (TMath::BinarySearch(Npads[ix],&YMIN[ix*NR],y));
551 if (y > YMIN[iy + ix*NR] + pitch)
continue;
555 l = iy + ix*NR + k*NS;
556 if (! LivePad[l])
continue;
572 LOG_INFO <<
"r " << r <<
"\tphi " << phi <<
"\tx " << x <<
"\tix " << ix
573 <<
"\tXMIN[ix] " << XMIN[ix] <<
"\tRMAX " << XMIN[ix] + XWID[ix];
574 if (ix < 44) { LOG_INFO <<
"\tXMIN[ix+1] " << XMIN[ix+1]; }
575 if (x <= XMIN[ix] + XWID[ix]) { LOG_INFO <<
" o.k."; }
580 mExB->UndoDistortion(pos2,pos4,k+1);
581 phi4 = TMath::ATan2(pos4[1],pos4[0]);
582 r4 = TMath::Sqrt(pos4[0]*pos4[0]+pos4[1]*pos4[1]);
584 acceptedRP->GetBinXYZ(acceptedRP->FindBin(r ,phi ,0),rbin,phibin,tempbin);
585 bingen = (rbin-1) + nr*(phibin-1);
587 acceptedRP->GetBinXYZ(acceptedRP->FindBin(r4,phi4,0),rbin,phibin,tempbin);
588 binfnd = (rbin-1) + nr*(phibin-1);
590 int zbin4 = Space3ChargePRZ->GetZaxis()->FindBin(z) - 1;
591 (*(RPMats[zbin4]))[binfnd][bingen]++;
592 (*(RPMatHs[zbin4]))[bingen]++;
593 (*(RMats[zbin4]))[binfndR][bingenR]++;
594 (*(RMatHs[zbin4]))[bingenR]++;
596 acceptedR->Fill(r,0);
597 acceptedP->Fill(phi,0);
598 acceptedRP->Fill(r,phi,0);
599 acceptedR->Fill(r,zbin);
600 acceptedP->Fill(phi,zbin);
601 acceptedRP->Fill(r,phi,zbin);
virtual void DoDistortion(const Float_t x[], Float_t Xprime[], Int_t Sector=-1)
Main Entry Point for requests to DO the E and B field distortions (for simulations) ...