#include <TClonesArray.h>
#include <TParticle.h>
#include <TVirtualMC.h>
#include "AliPHOSCPVDigit.h"
#include "AliPHOSGeometry.h"
#include "AliPHOSHit.h"
#include "AliPHOSv1.h"
#include "AliRun.h"
#include "AliMC.h"
#include "AliStack.h"
#include "AliPHOSSimParam.h"
ClassImp(AliPHOSv1)
AliPHOSv1::AliPHOSv1() : fCPVDigits("AliPHOSCPVDigit",20)
{
}
AliPHOSv1::AliPHOSv1(const char *name, const char *title):
AliPHOSv0(name,title), fCPVDigits("AliPHOSCPVDigit",20)
{
fHits= new TClonesArray("AliPHOSHit",1000) ;
gAlice->GetMCApp()->AddHitList(fHits) ;
fNhits = 0 ;
fIshunt = 2 ;
}
AliPHOSv1::~AliPHOSv1()
{
if ( fHits) {
fHits->Delete() ;
delete fHits ;
fHits = 0 ;
}
}
void AliPHOSv1::AddHit(Int_t shunt, Int_t primary, Int_t Id, Float_t * hits)
{
Int_t hitCounter ;
AliPHOSHit *newHit ;
AliPHOSHit *curHit ;
Bool_t deja = kFALSE ;
AliPHOSGeometry * geom = GetGeometry() ;
newHit = new AliPHOSHit(shunt, primary, Id, hits) ;
for ( hitCounter = fNhits-1 ; hitCounter >= 0 && !deja ; hitCounter-- ) {
curHit = static_cast<AliPHOSHit*>((*fHits)[hitCounter]) ;
if(curHit->GetPrimary() != primary) break ;
if( *curHit == *newHit ) {
*curHit + *newHit ;
deja = kTRUE ;
}
}
if ( !deja ) {
new((*fHits)[fNhits]) AliPHOSHit(*newHit) ;
Int_t relid[4] ;
geom->AbsToRelNumbering(Id, relid) ;
fNhits++ ;
}
delete newHit;
}
void AliPHOSv1::FinishPrimary()
{
}
void AliPHOSv1::FinishEvent()
{
AliDetector::FinishEvent();
}
void AliPHOSv1::StepManager(void)
{
Int_t relid[4] ;
Int_t absid ;
Float_t xyzte[5]={-1000.,-1000.,-1000.,0.,0.} ;
TLorentzVector pos ;
Int_t copy ;
Int_t moduleNumber ;
static Int_t idPCPQ = -1;
if (strstr(fTitle.Data(),"noCPV") == 0)
idPCPQ = TVirtualMC::GetMC()->VolId("PCPQ");
if( TVirtualMC::GetMC()->CurrentVolID(copy) == idPCPQ &&
(TVirtualMC::GetMC()->IsTrackEntering() ) &&
TVirtualMC::GetMC()->TrackCharge() != 0) {
TVirtualMC::GetMC() -> TrackPosition(pos);
Float_t xyzm[3], xyzd[3] ;
Int_t i;
for (i=0; i<3; i++) xyzm[i] = pos[i];
TVirtualMC::GetMC() -> Gmtod (xyzm, xyzd, 1);
Float_t xyd[3]={0,0,0} ;
xyd[0] = xyzd[0];
xyd[1] =-xyzd[2];
xyd[2] =-xyzd[1];
TLorentzVector pmom ;
TVirtualMC::GetMC() -> TrackMomentum(pmom);
Float_t pm[3], pd[3];
for (i=0; i<3; i++)
pm[i] = pmom[i];
TVirtualMC::GetMC() -> Gmtod (pm, pd, 2);
pmom[0] = pd[0];
pmom[1] =-pd[1];
pmom[2] =-pd[2];
TVirtualMC::GetMC()->CurrentVolOffID(3,moduleNumber);
moduleNumber--;
CPVDigitize(pmom,xyd,&fCPVDigits);
Float_t xmean = 0;
Float_t zmean = 0;
Float_t qsum = 0;
Int_t idigit,ndigits;
ndigits = fCPVDigits.GetEntriesFast();
for (idigit=0; idigit<ndigits-1; idigit++) {
AliPHOSCPVDigit *cpvDigit1 = static_cast<AliPHOSCPVDigit*>(fCPVDigits.UncheckedAt(idigit));
Float_t x1 = cpvDigit1->GetXpad() ;
Float_t z1 = cpvDigit1->GetYpad() ;
for (Int_t jdigit=idigit+1; jdigit<ndigits; jdigit++) {
AliPHOSCPVDigit *cpvDigit2 = static_cast<AliPHOSCPVDigit*>(fCPVDigits.UncheckedAt(jdigit));
Float_t x2 = cpvDigit2->GetXpad() ;
Float_t z2 = cpvDigit2->GetYpad() ;
if (x1==x2 && z1==z2) {
Float_t qsumpad = cpvDigit1->GetQpad() + cpvDigit2->GetQpad() ;
cpvDigit2->SetQpad(qsumpad) ;
fCPVDigits.RemoveAt(idigit) ;
}
}
}
fCPVDigits.Compress() ;
ndigits = fCPVDigits.GetEntriesFast();
for (idigit=0; idigit<ndigits; idigit++) {
AliPHOSCPVDigit *cpvDigit = static_cast<AliPHOSCPVDigit*>(fCPVDigits.UncheckedAt(idigit));
relid[0] = moduleNumber + 1 ;
relid[1] =-1 ;
relid[2] = cpvDigit->GetXpad() ;
relid[3] = cpvDigit->GetYpad() ;
GetGeometry()->RelToAbsNumbering(relid, absid) ;
xyzte[3] = TVirtualMC::GetMC()->TrackTime() ;
xyzte[4] = cpvDigit->GetQpad() ;
Int_t primary = gAlice->GetMCApp()->GetPrimary( gAlice->GetMCApp()->GetCurrentTrackNumber() );
AddHit(fIshunt, primary, absid, xyzte);
if (cpvDigit->GetQpad() > 0.02) {
xmean += cpvDigit->GetQpad() * (cpvDigit->GetXpad() + 0.5);
zmean += cpvDigit->GetQpad() * (cpvDigit->GetYpad() + 0.5);
qsum += cpvDigit->GetQpad();
}
}
fCPVDigits.Clear();
}
static Int_t idPXTL = TVirtualMC::GetMC()->VolId("PXTL");
if(TVirtualMC::GetMC()->CurrentVolID(copy) == idPXTL ) {
TVirtualMC::GetMC()->TrackPosition(pos) ;
xyzte[0] = pos[0] ;
xyzte[1] = pos[1] ;
xyzte[2] = pos[2] ;
Float_t lostenergy = TVirtualMC::GetMC()->Edep();
if ( TVirtualMC::GetMC()->IsTrackEntering() ){
Float_t xyzd[3] ;
TVirtualMC::GetMC() -> Gmtod (xyzte, xyzd, 1);
if (xyzd[1] < -GetGeometry()->GetCrystalSize(1)/2.+0.1){
Int_t parent = gAlice->GetMCApp()->GetCurrentTrackNumber() ;
TParticle * part = gAlice->GetMCApp()->Particle(parent) ;
Float_t vert[3],vertd[3] ;
vert[0]=part->Vx() ;
vert[1]=part->Vy() ;
vert[2]=part->Vz() ;
TVirtualMC::GetMC() -> Gmtod (vert, vertd, 1);
if(vertd[1]<-GetGeometry()->GetCrystalSize(1)/2.-0.1){
part->SetBit(kKeepBit);
while ( parent != -1 ) {
part = gAlice->GetMCApp()->Particle(parent) ;
part->SetBit(kKeepBit);
parent = part->GetFirstMother() ;
}
}
}
}
if ( lostenergy != 0 ) {
xyzte[3] = TVirtualMC::GetMC()->TrackTime() ;
TVirtualMC::GetMC()->CurrentVolOffID(10, moduleNumber) ;
Int_t strip ;
TVirtualMC::GetMC()->CurrentVolOffID(3, strip);
Int_t cell ;
TVirtualMC::GetMC()->CurrentVolOffID(2, cell);
Int_t row = GetGeometry()->GetEMCAGeometry()->GetNStripZ() - (strip - 1) % (GetGeometry()->GetEMCAGeometry()->GetNStripZ()) ;
Int_t col = (Int_t) TMath::Ceil((Double_t) strip/(GetGeometry()->GetEMCAGeometry()->GetNStripZ())) -1 ;
absid = (moduleNumber-1)*GetGeometry()->GetNCristalsInModule() +
row * 2 + (col*GetGeometry()->GetEMCAGeometry()->GetNCellsXInStrip() + (cell - 1) / 2)*GetGeometry()->GetNZ() - (cell & 1 ? 1 : 0);
Float_t lightYield = gRandom->Poisson(AliPHOSSimParam::GetInstance()->GetLightFactor() * lostenergy) ;
xyzte[4] = AliPHOSSimParam::GetInstance()->GetAPDFactor() * lightYield ;
Int_t primary ;
if(fIshunt == 2){
primary = gAlice->GetMCApp()->GetCurrentTrackNumber() ;
TParticle * part = gAlice->GetMCApp()->Particle(primary) ;
while ( !part->TestBit(kKeepBit) ) {
primary = part->GetFirstMother() ;
if(primary == -1){
primary = gAlice->GetMCApp()->GetPrimary( gAlice->GetMCApp()->GetCurrentTrackNumber() );
break ;
}
part = gAlice->GetMCApp()->Particle(primary) ;
}
}
else{
primary = gAlice->GetMCApp()->GetPrimary( gAlice->GetMCApp()->GetCurrentTrackNumber() );
}
AddHit(fIshunt, primary, absid, xyzte);
}
}
}
void AliPHOSv1::CPVDigitize (TLorentzVector p, Float_t *zxhit, TClonesArray *cpvDigits)
{
const Float_t kCelWr = GetGeometry()->GetPadSizePhi()/2;
const Float_t kDetR = 0.1;
const Float_t kdEdx = 4.0;
const Int_t kNgamz = 5;
const Int_t kNgamx = 9;
const Float_t kNoise = 0.03;
Float_t rnor1,rnor2;
Float_t hitX = zxhit[0];
Float_t hitZ =-zxhit[1];
Float_t pX = p.Px();
Float_t pZ =-p.Pz();
Float_t pNorm = p.Py();
Float_t eloss = kdEdx;
Float_t dZY = pZ/pNorm * GetGeometry()->GetCPVGasThickness();
Float_t dXY = pX/pNorm * GetGeometry()->GetCPVGasThickness();
gRandom->Rannor(rnor1,rnor2);
eloss *= (1 + kDetR*rnor1) *
TMath::Sqrt((1 + ( pow(dZY,2) + pow(dXY,2) ) / pow(GetGeometry()->GetCPVGasThickness(),2)));
Float_t zhit1 = hitZ + GetGeometry()->GetCPVActiveSize(1)/2 - dZY/2;
Float_t xhit1 = hitX + GetGeometry()->GetCPVActiveSize(0)/2 - dXY/2;
Float_t zhit2 = zhit1 + dZY;
Float_t xhit2 = xhit1 + dXY;
Int_t iwht1 = (Int_t) (xhit1 / kCelWr);
Int_t iwht2 = (Int_t) (xhit2 / kCelWr);
Int_t nIter;
Float_t zxe[3][5];
if (iwht1==iwht2) {
nIter = 2;
zxe[0][0] = (zhit1 + zhit2 - dZY*0.57735) / 2;
zxe[1][0] = (iwht1 + 0.5) * kCelWr;
zxe[2][0] = eloss/2;
zxe[0][1] = (zhit1 + zhit2 + dZY*0.57735) / 2;
zxe[1][1] = (iwht1 + 0.5) * kCelWr;
zxe[2][1] = eloss/2;
}
else if (TMath::Abs(iwht1-iwht2) != 1) {
nIter = 3;
Int_t iwht3 = (iwht1 + iwht2) / 2;
Float_t xwht1 = (iwht1 + 0.5) * kCelWr;
Float_t xwht2 = (iwht2 + 0.5) * kCelWr;
Float_t xwht3 = (iwht3 + 0.5) * kCelWr;
Float_t xwr13 = (xwht1 + xwht3) / 2;
Float_t xwr23 = (xwht2 + xwht3) / 2;
Float_t dxw1 = xhit1 - xwr13;
Float_t dxw2 = xhit2 - xwr23;
Float_t egm1 = TMath::Abs(dxw1) / ( TMath::Abs(dxw1) + TMath::Abs(dxw2) + kCelWr );
Float_t egm2 = TMath::Abs(dxw2) / ( TMath::Abs(dxw1) + TMath::Abs(dxw2) + kCelWr );
Float_t egm3 = kCelWr / ( TMath::Abs(dxw1) + TMath::Abs(dxw2) + kCelWr );
zxe[0][0] = (dXY*(xwr13-xwht1)/dXY + zhit1 + zhit1) / 2;
zxe[1][0] = xwht1;
zxe[2][0] = eloss * egm1;
zxe[0][1] = (dXY*(xwr23-xwht1)/dXY + zhit1 + zhit2) / 2;
zxe[1][1] = xwht2;
zxe[2][1] = eloss * egm2;
zxe[0][2] = dXY*(xwht3-xwht1)/dXY + zhit1;
zxe[1][2] = xwht3;
zxe[2][2] = eloss * egm3;
}
else {
nIter = 2;
Float_t xwht1 = (iwht1 + 0.5) * kCelWr;
Float_t xwht2 = (iwht2 + 0.5) * kCelWr;
Float_t xwr12 = (xwht1 + xwht2) / 2;
Float_t dxw1 = xhit1 - xwr12;
Float_t dxw2 = xhit2 - xwr12;
Float_t egm1 = TMath::Abs(dxw1) / ( TMath::Abs(dxw1) + TMath::Abs(dxw2) );
Float_t egm2 = TMath::Abs(dxw2) / ( TMath::Abs(dxw1) + TMath::Abs(dxw2) );
zxe[0][0] = (zhit1 + zhit2 - dZY*egm1) / 2;
zxe[1][0] = xwht1;
zxe[2][0] = eloss * egm1;
zxe[0][1] = (zhit1 + zhit2 + dZY*egm2) / 2;
zxe[1][1] = xwht2;
zxe[2][1] = eloss * egm2;
}
Int_t nCellZ = GetGeometry()->GetNumberOfCPVPadsZ();
Int_t nCellX = GetGeometry()->GetNumberOfCPVPadsPhi();
Int_t nz3 = (kNgamz+1)/2;
Int_t nx3 = (kNgamx+1)/2;
cpvDigits->Expand(nIter*kNgamx*kNgamz);
TClonesArray &ldigits = *(static_cast<TClonesArray *>(cpvDigits));
for (Int_t iter=0; iter<nIter; iter++) {
Float_t zhit = zxe[0][iter];
Float_t xhit = zxe[1][iter];
Float_t qhit = zxe[2][iter];
Float_t zcell = zhit / GetGeometry()->GetPadSizeZ();
Float_t xcell = xhit / GetGeometry()->GetPadSizePhi();
if ( zcell<=0 || xcell<=0 ||
zcell>=nCellZ || xcell>=nCellX) return;
Int_t izcell = (Int_t) zcell;
Int_t ixcell = (Int_t) xcell;
Float_t zc = zcell - izcell - 0.5;
Float_t xc = xcell - ixcell - 0.5;
for (Int_t iz=1; iz<=kNgamz; iz++) {
Int_t kzg = izcell + iz - nz3;
if (kzg<=0 || kzg>nCellZ) continue;
Float_t zg = (Float_t)(iz-nz3) - zc;
for (Int_t ix=1; ix<=kNgamx; ix++) {
Int_t kxg = ixcell + ix - nx3;
if (kxg<=0 || kxg>nCellX) continue;
Float_t xg = (Float_t)(ix-nx3) - xc;
Float_t qpad = CPVPadResponseFunction(qhit,zg,xg);
qpad += kNoise*rnor2;
if (qpad<0) continue;
new(ldigits[cpvDigits->GetEntriesFast()]) AliPHOSCPVDigit(kxg,kzg,qpad);
}
}
}
}
Float_t AliPHOSv1::CPVPadResponseFunction(Float_t qhit, Float_t zhit, Float_t xhit) {
Double_t dz = GetGeometry()->GetPadSizeZ() / 2;
Double_t dx = GetGeometry()->GetPadSizePhi() / 2;
Double_t z = zhit * GetGeometry()->GetPadSizeZ();
Double_t x = xhit * GetGeometry()->GetPadSizePhi();
Double_t amplitude = qhit *
(CPVCumulPadResponse(z+dz,x+dx) - CPVCumulPadResponse(z+dz,x-dx) -
CPVCumulPadResponse(z-dz,x+dx) + CPVCumulPadResponse(z-dz,x-dx));
return (Float_t)amplitude;
}
Double_t AliPHOSv1::CPVCumulPadResponse(Double_t x, Double_t y) {
const Double_t kA=1.0;
const Double_t kB=0.7;
Double_t r2 = x*x + y*y;
Double_t xy = x*y;
Double_t cumulPRF = 0;
for (Int_t i=0; i<=4; i++) {
Double_t b1 = (2*i + 1) * kB;
cumulPRF += TMath::Power(-1,i) * TMath::ATan( xy / (b1*TMath::Sqrt(b1*b1 + r2)) );
}
cumulPRF *= kA/(2*TMath::Pi());
return cumulPRF;
}