////////////////////////////////////////////////////////////////////////////
+#include <TGeoGlobalMagField.h>
#include "AliITSCalibrationSPD.h"
#include "AliITSClusterFinderV2SPD.h"
#include "AliITSRecPoint.h"
#include "AliITSdigitSPD.h"
#include "AliITSFOSignalsSPD.h"
#include "AliITSRecPointContainer.h"
+#include "AliMagF.h"
+#include "AliITSsegmentationSPD.h"
ClassImp(AliITSClusterFinderV2SPD)
Int_t AliITSClusterFinderV2SPD::ClustersSPD(AliBin* bins, TClonesArray* digits,TClonesArray* clusters,Int_t maxBins,Int_t nzbins,Int_t iModule,Bool_t rawdata){
//Cluster finder for SPD (from digits and from rawdata)
+ const Double_t kmictocm = 1.0e-4; // convert microns to cm.
+ const Double_t defaultField = 5.0; // default Bz value at which Tan(theta_Lorentz) is given in RecoParam
static AliITSRecoParam *repa = NULL;
if(!repa){
}
const TGeoHMatrix *mT2L=AliITSgeomTGeo::GetTracking2LocalMatrix(iModule);
+ // Lorentz angle correction
+ Double_t tanLorentzAngle=0;
+ AliITSsegmentationSPD *seg = (AliITSsegmentationSPD*)(GetDetTypeRec()->GetSegmentationModel(0));
+ Double_t thick = 0.5*kmictocm*seg->Dy(); // Half Thickness in cm
+ if(repa->GetCorrectLorentzAngleSPD()) { // only if CorrectLorentzAngleSPD required
+ // here retrieve the value of the field
+ AliMagF* field = dynamic_cast<AliMagF*>(TGeoGlobalMagField::Instance()->GetField());
+ if (field == 0)
+ AliError("Cannot get magnetic field from TGeoGlobalMagField");
+ Float_t magField = field->SolenoidField();
+ tanLorentzAngle=repa->GetTanLorentzAngleHolesSPD() * magField / defaultField ;
+ }
+ //
+
if (repa->GetSPDRemoveNoisyFlag()) {
// Loop on noisy pixels and reset them
AliITSCalibrationSPD *cal =
y -= fHwSPD;
z -= fHlSPD;
+ // Lorentz drift effect in local y
+ y -= tanLorentzAngle*thick;
+ //
+
Float_t hit[5]; //y,z,sigma(y)^2, sigma(z)^2, charge
{
Double_t loc[3]={y,0.,z},trk[3]={0.,0.,0.};
// //
///////////////////////////////////////////////////////////////////////////
+#include "AliITSClusterFinderV2SSD.h"
+
#include <Riostream.h>
-#include "AliLog.h"
+#include <TGeoGlobalMagField.h>
-#include "AliITSClusterFinderV2SSD.h"
+#include "AliLog.h"
+#include "AliMagF.h"
#include "AliITSRecPoint.h"
#include "AliITSRecPointContainer.h"
#include "AliITSgeomTGeo.h"
ClassImp(AliITSClusterFinderV2SSD)
-AliITSClusterFinderV2SSD::AliITSClusterFinderV2SSD(AliITSDetTypeRec* dettyp):AliITSClusterFinder(dettyp),
- fLastSSD1(AliITSgeomTGeo::GetModuleIndex(6,1,1)-1)
+ AliITSClusterFinderV2SSD::AliITSClusterFinderV2SSD(AliITSDetTypeRec* dettyp):AliITSClusterFinder(dettyp),fLastSSD1(AliITSgeomTGeo::GetModuleIndex(6,1,1)-1), fLorentzShiftP(0), fLorentzShiftN(0)
{
//Default constructor
+ static AliITSRecoParam *repa = NULL;
+ if(!repa){
+ repa = (AliITSRecoParam*) AliITSReconstructor::GetRecoParam();
+ if(!repa){
+ repa = AliITSRecoParam::GetHighFluxParam();
+ AliWarning("Using default AliITSRecoParam class");
+ }
+ }
+ if (repa->GetCorrectLorentzAngleSSD()) {
+ AliMagF* field = dynamic_cast<AliMagF*>(TGeoGlobalMagField::Instance()->GetField());
+ if (field == 0)
+ AliError("Cannot get magnetic field from TGeoGlobalMagField");
+ Float_t Bfield = field->SolenoidField();
+ // NB: spatial shift has opposite sign for lay 5 and 6, but strip numbering also changes direction, so no sign-change
+ // Shift due to ExB on drift N-side, units: strip width
+ fLorentzShiftP = -repa->GetTanLorentzAngleElectronsSSD() * 150.e-4/95.e-4 * Bfield / 5.0;
+ // Shift due to ExB on drift P-side, units: strip width
+ fLorentzShiftN = -repa->GetTanLorentzAngleHolesSSD() * 150.e-4/95.e-4 * Bfield / 5.0;
+ AliDebug(1,Form("Bfield %f Lorentz Shift P-side %f N-side %f",Bfield,fLorentzShiftN,fLorentzShiftP));
+ }
}
//______________________________________________________________________
-AliITSClusterFinderV2SSD::AliITSClusterFinderV2SSD(const AliITSClusterFinderV2SSD &cf) : AliITSClusterFinder(cf), fLastSSD1(cf.fLastSSD1)
+AliITSClusterFinderV2SSD::AliITSClusterFinderV2SSD(const AliITSClusterFinderV2SSD &cf) : AliITSClusterFinder(cf), fLastSSD1(cf.fLastSSD1), fLorentzShiftP(cf.fLorentzShiftP), fLorentzShiftN(cf.fLorentzShiftN)
{
// Copy constructor
}
cout<<endl;
cout<<endl;
*/
+ Int_t layer = 4;
+ if (fModule>fLastSSD1)
+ layer = 5;
//--------------------------------------------------------
// start 1D-clustering from the first digit in the digits array
if(flag5) {
//cout<<"here1"<<endl;
- c[*n].SetY(y/q);
+ Float_t dLorentz = 0;
+ if (!flag) { // P-side is neg clust
+ dLorentz = fLorentzShiftN;
+ }
+ else { // N-side is p clust
+ dLorentz = fLorentzShiftP;
+ }
+ c[*n].SetY(y/q+dLorentz);
c[*n].SetQ(q);
c[*n].SetNd(nd);
CheckLabels2(milab);
//Split suspiciously big cluster
if (nd>4&&nd<25) {
- c[*n].SetY(y/q-0.25*nd);
+ c[*n].SetY(y/q-0.25*nd+dLorentz);
c[*n].SetQ(0.5*q);
(*n)++;
if (*n==kMax) {
Error("FindClustersSSD","Too many 1D clusters !");
return;
}
- c[*n].SetY(y/q+0.25*nd);
+ c[*n].SetY(y/q+0.25*nd+dLorentz);
c[*n].SetQ(0.5*q);
c[*n].SetNd(nd);
c[*n].SetLabels(milab);
if(flag5) {
// cout<<"here2"<<endl;
-
- c[*n].SetY(y/q);
+ Float_t dLorentz = 0;
+ if (!flag) { // P-side is neg clust
+ dLorentz = fLorentzShiftN;
+ }
+ else { // N-side is p clust
+ dLorentz = fLorentzShiftP;
+ }
+
+ c[*n].SetY(y/q + dLorentz);
c[*n].SetQ(q);
c[*n].SetNd(nd);
c[*n].SetLabels(lab);
//Split suspiciously big cluster
if (nd>4 && nd<25) {
- c[*n].SetY(y/q-0.25*nd);
+ c[*n].SetY(y/q-0.25*nd + dLorentz);
c[*n].SetQ(0.5*q);
(*n)++;
if (*n==kMax) {
Error("FindClustersSSD","Too many 1D clusters !");
return;
}
- c[*n].SetY(y/q+0.25*nd);
+ c[*n].SetY(y/q+0.25*nd + dLorentz);
c[*n].SetQ(0.5*q);
c[*n].SetNd(nd);
c[*n].SetLabels(lab);
void AliITSClusterFinderV2SSD::RawdataToClusters(AliRawReader* rawReader){
- //------------------------------------------------------------
+ //------------------------------------------------------------
// This function creates ITS clusters from raw data
//------------------------------------------------------------
rawReader->Reset();
//CM channels are always present even everything is suppressed
continue;
}
+
+ Int_t layer = 4;
+ if (fModule>fLastSSD1)
+ layer = 5;
AliITSCalibrationSSD* cal = (AliITSCalibrationSSD*)fDetTypeRec->GetCalibrationModel(fModule);
if( !cal ){
Int_t nDigits = 0;
Int_t ostrip = -2;
Bool_t snFlag = 0;
+
+ Float_t dLorentz = 0;
+ if (side==0) { // P-side is neg clust
+ dLorentz = fLorentzShiftN;
+ }
+ else { // N-side is pos clust
+ dLorentz = fLorentzShiftP;
+ }
Int_t n = nStrips[adc][side];
for( int istr = 0; istr<n+1; istr++ ){
}else {
Ali1Dcluster &cluster = clusters1D[side][nClusters1D[side]++];
- cluster.SetY( y / q + dStrip);
+ cluster.SetY( y / q + dStrip + dLorentz);
cluster.SetQ(q);
cluster.SetNd(nDigits);
cluster.SetLabels(lab);
if( repa->GetUseUnfoldingInClusterFinderSSD()
&& nDigits > 4 && nDigits < 25
){
- cluster.SetY(y/q + dStrip - 0.25*nDigits);
+ cluster.SetY(y/q + dStrip - 0.25*nDigits + dLorentz);
cluster.SetQ(0.5*q);
Ali1Dcluster& cluster2 = clusters1D[side][nClusters1D[side]++];
- cluster2.SetY(y/q + dStrip + 0.25*nDigits);
+ cluster2.SetY(y/q + dStrip + 0.25*nDigits + dLorentz);
cluster2.SetQ(0.5*q);
cluster2.SetNd(nDigits);
cluster2.SetLabels(lab);
return (AliITSCalibrationSSD*) fDetTypeRec->GetCalibrationModel(mod);}
Int_t fLastSSD1; //index of the last SSD1 detector
+ Float_t fLorentzShiftP; // Shift due to ExB on drift N-side @ actual B field, layer 5, units: strip width
+ Float_t fLorentzShiftN; // Shift due to ExB on drift P-side @ actual B field, layer 5, units: strip width
static Short_t* fgPairs; //array used to build positive-negative pairs
static Int_t fgPairsSize; //actual size of pairs array
static const Float_t fgkCosmic2008StripShifts[16][9]; // Shifts for 2007/2008 Cosmic data (timing problem)
fMultCutMaxDCA(1.),
//
fCorrectLorentzAngleSPD(kFALSE),
-fLorentzAngleHolesSPD(0.),
+fTanLorentzAngleHolesSPD(0.017455), // tan(1 degree)
fCorrectLorentzAngleSSD(kFALSE),
-fLorentzAngleHolesSSD(0.),
-fLorentzAngleElectronsSSD(0.),
+fTanLorentzAngleHolesSSD(0.016), // tan(0.94 degrees)
+fTanLorentzAngleElectronsSSD(0.068), // tan(3.98 degrees)
//
fESDV0Params(NULL)
{
//
// Lorentz angle
Bool_t GetCorrectLorentzAngleSPD() const {return fCorrectLorentzAngleSPD;}
- Float_t GetLorentzAngleHolesSPD() const {return fLorentzAngleHolesSPD;}
+ Float_t GetTanLorentzAngleHolesSPD() const {return fTanLorentzAngleHolesSPD;}
Bool_t GetCorrectLorentzAngleSSD() const {return fCorrectLorentzAngleSSD;}
- Float_t GetLorentzAngleHolesSSD() const {return fLorentzAngleHolesSSD;}
- Float_t GetLorentzAngleElectronsSSD() const {return fLorentzAngleElectronsSSD;}
+ Float_t GetTanLorentzAngleHolesSSD() const {return fTanLorentzAngleHolesSSD;}
+ Float_t GetTanLorentzAngleElectronsSSD() const {return fTanLorentzAngleElectronsSSD;}
void SetCorrectLorentzAngleSPD(Bool_t flag) {fCorrectLorentzAngleSPD=flag;}
- void SetLorentzAngleHolesSPD(Float_t la) {fLorentzAngleHolesSPD=la;}
+ void SetTanLorentzAngleHolesSPD(Float_t la) {fTanLorentzAngleHolesSPD=la;}
void SetCorrectLorentzAngleSSD(Bool_t flag) {fCorrectLorentzAngleSSD=flag;}
- void SetLorentzAngleHolesSSD(Float_t la) {fLorentzAngleHolesSSD=la;}
- void SetLorentzAngleElectronsSSD(Float_t la) {fLorentzAngleElectronsSSD=la;}
+ void SetTanLorentzAngleHolesSSD(Float_t la) {fTanLorentzAngleHolesSSD=la;}
+ void SetTanLorentzAngleElectronsSSD(Float_t la) {fTanLorentzAngleElectronsSSD=la;}
//
enum {fgkMaxClusterPerLayer=70000}; //7000*10; // max clusters per layer
//
// Lorentz angle
Bool_t fCorrectLorentzAngleSPD; // flag to enable correction
- Float_t fLorentzAngleHolesSPD; // angle for holes in SPD
+ Float_t fTanLorentzAngleHolesSPD; // angle for holes in SPD
Bool_t fCorrectLorentzAngleSSD; // flag to enable correction
- Float_t fLorentzAngleHolesSSD; // angle for holes in SSD
- Float_t fLorentzAngleElectronsSSD; // angle for electrons in SSD
+ Float_t fTanLorentzAngleHolesSSD; // tan(angle) for holes in SSD @ B = 0.5 T
+ Float_t fTanLorentzAngleElectronsSSD; // tan(angle) for electrons in SSD @ B = 0.5 T
private:
AliESDV0Params * fESDV0Params; // declare the AliESDV0Params to be able to used in AliITSV0Finder
AliITSRecoParam(const AliITSRecoParam & param);
AliITSRecoParam & operator=(const AliITSRecoParam ¶m);
- ClassDef(AliITSRecoParam,33) // ITS reco parameters
+ ClassDef(AliITSRecoParam,34) // ITS reco parameters
};
#endif
fSDDChargeLoss(fgkSDDChargeLossDefault),
fSDDTrigDelay(fgkSDDTrigDelayDefault),
fSDDRawFormat(7),
+fSSDLorentzDrift(kTRUE),
fSSDCouplingPR(0),
fSSDCouplingPL(0),
fSSDCouplingNR(0),
fSDDChargeLoss(simpar.fSDDChargeLoss),
fSDDTrigDelay(simpar.fSDDTrigDelay),
fSDDRawFormat(simpar.fSDDRawFormat),
+fSSDLorentzDrift(simpar.fSSDLorentzDrift),
fSSDCouplingPR(simpar.fSSDCouplingPR),
fSSDCouplingPL(simpar.fSSDCouplingPL),
fSSDCouplingNR(simpar.fSSDCouplingNR),
printf("Raw Data Format = %d\n",fSDDRawFormat);
printf("\n");
printf("===== SSD parameters =====\n");
+ printf("Flag to add Lorentz Drift = %d\n",fSSDLorentzDrift);
printf("Coupling PR = %f\n",fSSDCouplingPR);
printf("Coupling PL = %f\n",fSSDCouplingPL);
printf("Coupling NR = %f\n",fSSDCouplingNR);
void SetSDDRawDataFormatCarlos() {fSDDRawFormat=7;}
void SetSDDRawDataFormatFixLen8bitEncoded() {fSDDRawFormat=0;}
Char_t GetSDDRawDataFormat() const {return fSDDRawFormat;}
+
+ // Use Lorentz's angle
+ void SetSSDLorentzDrift(Bool_t ison) {fSSDLorentzDrift=ison;}
+ Bool_t GetSSDLorentzDrift() const {return fSSDLorentzDrift;}
+
Int_t GetSSDZSThreshold() const { // ZS threshold
return fSSDZSThreshold; }
virtual void SetSSDZSThreshold(Int_t zsth) { fSSDZSThreshold = zsth; }
Float_t fSDDTrigDelay; // SDD time-zero
Char_t fSDDRawFormat; // Index for SDD RawFormat
+ Bool_t fSSDLorentzDrift; // Flag to decide whether to simulate the Lorentz Drift or not in SSD
+
Double_t fSSDCouplingPR; // SSD couplings
Double_t fSSDCouplingPL; // SSD couplings
Double_t fSSDCouplingNR; // SSD couplings
#include <TObjArray.h>
#include <TRandom.h>
+#include <TGeoGlobalMagField.h>
#include "AliITSmodule.h"
#include "AliITSMapA2.h"
#include "AliITSpList.h"
#include "AliITShit.h"
#include "AliITSdigitSSD.h"
#include "AliRun.h"
+#include "AliMagF.h"
#include "AliITSgeom.h"
#include "AliITSsimulationSSD.h"
#include "AliITSTableSSD.h"
fIonE(0.0),
fDifConst(),
fDriftVel(),
-fTimeResponse(NULL){
+fTimeResponse(NULL),
+fLorentz(kFALSE),
+fTanLorAngP(0),
+fTanLorAngN(0)
+{
//default Constructor
//Inputs:
// none.
fIonE(0.0),
fDifConst(),
fDriftVel(),
-fTimeResponse(NULL){
+fTimeResponse(NULL),
+fLorentz(kFALSE),
+fTanLorAngP(0),
+fTanLorAngN(0)
+{
// Constructor
// Input:
// AliITSDetTypeSim Pointer to the SSD dettype to be used
// Return
// none.
AliITSsegmentationSSD* seg = (AliITSsegmentationSSD*)GetSegmentationModel(2);
+ AliITSSimuParam* simpar = fDetType->GetSimuParam();
SetDriftVelocity(); // use default values in .h file
SetIonizeE(); // use default values in .h file
SetDiffConst(); // use default values in .h file
fpList = new AliITSpList(2,GetNStrips());
fMapA2 = new AliITSMapA2(seg);
+ SetLorentzDrift(simpar->GetSSDLorentzDrift());
+ if (fLorentz) SetTanLorAngle();
}
+
+//______________________________________________________________________
+Bool_t AliITSsimulationSSD::SetTanLorAngle() {
+ // This function set the Tangent of the Lorentz angles.
+ // output: Bool_t : kTRUE in case of success
+ //
+
+ if(!fDetType) {
+ AliError("AliITSsimulationSPD::SetTanLorAngle: AliITSDetTypeSim* fDetType not set ");
+ return kFALSE;}
+
+ AliITSSimuParam* simpar = fDetType->GetSimuParam();
+ AliMagF* fld = (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
+ if (!fld) AliFatal("The field is not initialized");
+ Double_t bz = fld->SolenoidField();
+
+ fTanLorAngN = TMath::Tan( simpar->LorentzAngleElectron(bz) );
+ fTanLorAngP = TMath::Tan( simpar->LorentzAngleHole(bz) );
+
+ return kTRUE;
+}
+
//______________________________________________________________________
AliITSsimulationSSD& AliITSsimulationSSD::operator=(
const AliITSsimulationSSD &s){
this->fDriftVel[0] = s.fDriftVel[0];
this->fDriftVel[1] = s.fDriftVel[1];
this->fTimeResponse = s.fTimeResponse;
+ this->fLorentz = s.fLorentz;
+ this->fTanLorAngP = s.fTanLorAngP;
+ this->fTanLorAngN = s.fTanLorAngN;
return *this;
}
/*
fIonE(source.fIonE),
fDifConst(),
fDriftVel(),
-fTimeResponse(source.fTimeResponse){
+fTimeResponse(source.fTimeResponse),
+fLorentz(source.fLorentz),
+fTanLorAngP(source.fTanLorAngP),
+fTanLorAngN(source.fTanLorAngN)
+{
// copy constructor
fDifConst[0] = source.fDifConst[0];
fDifConst[1] = source.fDifConst[1];
module = mod->GetIndex();
if ( mod->GetLayer() == 6 ) seg->SetLayer(6);
if ( mod->GetLayer() == 5 ) seg->SetLayer(5);
+
for(Int_t i=0; i<nhits; i++) {
// LineSegmentL returns 0 if the hit is entering
// If hits is exiting returns positions of entering and exiting hits
Double_t tdrift[2] = {0.,0.}; // time of drift
Double_t w;
Double_t inf[2], sup[2], par0[2];
-
+
+ // Set up corrections for Lorentz drift (ExB)
+ Double_t TanLorAngP = fTanLorAngP;
+ Double_t TanLorAngN = fTanLorAngN;
+ if(seg->GetLayer()==6) {
+ TanLorAngP = -1.*fTanLorAngP;
+ TanLorAngN = -1.*fTanLorAngN;
+ }
+
// Steps in the module are determined "manually" (i.e. No Geant)
// NumOfSteps divide path between entering and exiting hits in steps
Int_t numOfSteps = NumOfSteps(x1, y1, z1, dex, dey, dez);
y=-y; // Lay6 module has sensor up-side-down!!!
}
- // w is the coord. perpendicular to the strips
- // Float_t xp=x*1.e+4,zp=z*1.e+4; // microns
- Float_t xp=x,zp=z;
- seg->GetPadTxz(xp,zp);
-
Int_t k;
//---------------------------------------------------------
// Pside
//------------------------------------------------------------
k=0;
+
+ // w is the coord. perpendicular to the strips
+ // Float_t xp=x*1.e+4,zp=z*1.e+4; // microns
+ Float_t xp=x,zp=z;
+
+ // correction for the Lorentz's angle
+ if(fLorentz) {
+ Float_t deltaxp = (y+(seg->Dy()*1.0E-4)/2)*TanLorAngP;
+ xp+=deltaxp;
+ }
+
+ seg->GetPadTxz(xp,zp);
// calculate drift time
// y is the minimum path
if(GetDebug(4)) cout << "Dead SSD region, x,z="<<x<<","<<z<<endl;
return; // There are dead region on the SSD sensitive volume!!!
} // end if
-
- // sigma is the standard deviation of the diffusion gaussian
+ // sigma is the standard deviation of the diffusion gaussian
if(tdrift[k]<0) return;
sigma[k] = TMath::Sqrt(2*GetDiffConst(k)*tdrift[k]);
// Nside
//-------------------------------------------------------
k=1;
+
+ xp=x; zp=z;
+
+ // correction for the Lorentz's angle
+ if(fLorentz) {
+ Float_t deltaxn = ((seg->Dy()*1.0E-4)/2-y)*TanLorAngN;
+ xp+=deltaxn;
+ }
+
+
+ seg->GetPadTxz(xp,zp);
+
tdrift[1] = ((seg->Dy()*1.0E-4)/2-y)/GetDriftVelocity(1);
//tang[k]=TMath::Tan(tang[k]);
//Sets the Drift velocity for the P and N sides
void SetDriftVelocity(Double_t v0=0.86E+06,Double_t v1=2.28E+06)
{fDriftVel[0] = v0;fDriftVel[1] = v1;}
+
+
+ // Decide whether to use or not the Lorentz drift
+ void SetLorentzDrift(Bool_t b=kFALSE)
+ {fLorentz=b; if(fLorentz) SetTanLorAngle();};
+ // Set the Lorentz angles
+ Bool_t SetTanLorAngle();
+ // Getter for the Lorentz angles
+ Double_t GetTanLorAngleP() const {return fTanLorAngP;};
+ Double_t GetTanLorAngleN() const {return fTanLorAngN;};
+ //
+
+
// Standard ascii class print function
void Print(ostream *os);
// Standard ascii class read function
TF1 *fTimeResponse; // signal time response function
+ Bool_t fLorentz; // kTRUE if Lorentz drift has been allowed
+ Double_t fTanLorAngP; //! Tangent of the Lorentz Angle for holes
+ Double_t fTanLorAngN; //! Tangent of the Lorentz Angle for electrons
+
+
ClassDef(AliITSsimulationSSD,3) // SSD signal simulation class
};