+void AliPHOSv1::CPVDigitize (TLorentzVector p, Float_t *zxhit, TClonesArray *cpvDigits)
+{
+ // ------------------------------------------------------------------------
+ // Digitize one CPV hit:
+ // On input take exact 4-momentum p and position zxhit of the hit,
+ // find the pad response around this hit and
+ // put the amplitudes in the pads into array digits
+ //
+ // Author: Yuri Kharlov (after Serguei Sadovsky)
+ // 2 October 2000
+ // ------------------------------------------------------------------------
+
+ const Float_t kCelWr = GetGeometry()->GetPadSizePhi()/2; // Distance between wires (2 wires above 1 pad)
+ const Float_t kDetR = 0.1; // Relative energy fluctuation in track for 100 e-
+ const Float_t kdEdx = 4.0; // Average energy loss in CPV;
+ const Int_t kNgamz = 5; // Ionization size in Z
+ const Int_t kNgamx = 9; // Ionization size in Phi
+ const Float_t kNoise = 0.03; // charge noise in one pad
+
+ Float_t rnor1,rnor2;
+
+ // Just a reminder on axes notation in the CPV module:
+ // axis Z goes along the beam
+ // axis X goes across the beam in the module plane
+ // axis Y is a normal to the module plane showing from the IP
+
+ 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;
+
+//Info("CPVDigitize", "YVK : %f %f | %f %f %d", hitX, hitZ, pX, pZ, pNorm) ;
+
+ 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); // wire (x) coordinate "in"
+ Int_t iwht2 = (Int_t) (xhit2 / kCelWr); // wire (x) coordinate "out"
+
+ Int_t nIter;
+ Float_t zxe[3][5];
+ if (iwht1==iwht2) { // incline 1-wire hit
+ 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) { // incline 3-wire hit
+ nIter = 3;
+ Int_t iwht3 = (iwht1 + iwht2) / 2;
+ Float_t xwht1 = (iwht1 + 0.5) * kCelWr; // wire 1
+ Float_t xwht2 = (iwht2 + 0.5) * kCelWr; // wire 2
+ Float_t xwht3 = (iwht3 + 0.5) * kCelWr; // wire 3
+ Float_t xwr13 = (xwht1 + xwht3) / 2; // center 13
+ Float_t xwr23 = (xwht2 + xwht3) / 2; // center 23
+ 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 { // incline 2-wire hit
+ 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;
+ }
+
+ // Finite size of ionization region
+
+ 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;
+
+ // Now calculate pad response
+ Float_t qpad = CPVPadResponseFunction(qhit,zg,xg);
+ qpad += kNoise*rnor2;
+ if (qpad<0) continue;
+
+ // Fill the array with pad response ID and amplitude
+ new(ldigits[cpvDigits->GetEntriesFast()]) AliPHOSCPVDigit(kxg,kzg,qpad);
+ }
+ }