ROOT logo
/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/


#include <TClass.h>
#include <TFile.h>
#include <TSystem.h>
#include <TPRegexp.h>

#include "AliMagF.h"
#include "AliMagWrapCheb.h"
#include "AliLog.h"

ClassImp(AliMagF)

const Double_t AliMagF::fgkSol2DipZ    =  -700.;  
const UShort_t AliMagF::fgkPolarityConvention = AliMagF::kConvLHC;
/*
 Explanation for polarity conventions: these are the mapping between the
 current signs and main field components in L3 (Bz) and Dipole (Bx) (in Alice frame)
 1) kConvMap2005: used for the field mapping in 2005
 positive L3  current -> negative Bz
 positive Dip current -> positive Bx 
 2) kConvMapDCS2008: defined by the microswitches/cabling of power converters as of 2008 - 1st half 2009
 positive L3  current -> positive Bz
 positive Dip current -> positive Bx
 3) kConvLHC : defined by LHC
 positive L3  current -> positive Bz
 positive Dip current -> negative Bx
 
 Note: only "negative Bz(L3) with postive Bx(Dipole)" and its inverse was mapped in 2005. Hence 
 the GRP Manager will reject the runs with the current combinations (in the convention defined by the
 static Int_t AliMagF::GetPolarityConvention()) which do not lead to such field polarities.

 ----------------------------------------------- 

 Explanation on integrals in the TPC region
 GetTPCInt(xyz,b) and GetTPCRatInt(xyz,b) give integrals from point (x,y,z) to point (x,y,0) 
 (irrespectively of the z sign) of the following:
 TPCInt:    b contains int{bx}, int{by}, int{bz}
 TPCRatInt: b contains int{bx/bz}, int{by/bz}, int{(bx/bz)^2+(by/bz)^2}
  
 The same applies to integral in cylindrical coordinates:
 GetTPCIntCyl(rphiz,b)
 GetTPCIntRatCyl(rphiz,b)
 They accept the R,Phi,Z coordinate (-pi<phi<pi) and return the field 
 integrals in cyl. coordinates.

 Thus, to compute the integral from arbitrary xy_z1 to xy_z2, one should take
 b = b1-b2 with b1 and b2 coming from GetTPCInt(xy_z1,b1) and GetTPCInt(xy_z2,b2)

 Note: the integrals are defined for the range -300<Z<300 and 0<R<300
*/
//_______________________________________________________________________
AliMagF::AliMagF():
  TVirtualMagField(),
  fMeasuredMap(0),
  fMapType(k5kG),
  fSolenoid(0),
  fBeamType(kNoBeamField),
  fBeamEnergy(0),
  //
  fInteg(0),
  fPrecInteg(0),
  fFactorSol(1.),
  fFactorDip(1.),
  fMax(15),
  fDipoleOFF(kFALSE),
  //
  fQuadGradient(0),
  fDipoleField(0),
  fCCorrField(0), 
  fACorr1Field(0),
  fACorr2Field(0),
  fParNames("","")
{
  // Default constructor
  //
}

//_______________________________________________________________________
AliMagF::AliMagF(const char *name, const char* title, Double_t factorSol, Double_t factorDip, 
		 BMap_t maptype, BeamType_t bt, Double_t be,Int_t integ, Double_t fmax, const char* path):
  TVirtualMagField(name),
  fMeasuredMap(0),
  fMapType(maptype),
  fSolenoid(0),
  fBeamType(bt),
  fBeamEnergy(be),
  //
  fInteg(integ),
  fPrecInteg(1),
  fFactorSol(1.),
  fFactorDip(1.),
  fMax(fmax),
  fDipoleOFF(factorDip==0.),
  //
  fQuadGradient(0),
  fDipoleField(0),
  fCCorrField(0), 
  fACorr1Field(0),
  fACorr2Field(0),
  fParNames("","")
{
  // Initialize the field with Geant integration option "integ" and max field "fmax,
  // Impose scaling of parameterized L3 field by factorSol and of dipole by factorDip.
  // The "be" is the energy of the beam in GeV/nucleon
  //
  SetTitle(title);
  if(integ<0 || integ > 2) {
    AliWarning(Form("Invalid magnetic field flag: %5d; Helix tracking chosen instead",integ));
    fInteg = 2;
  }
  if (fInteg == 0) fPrecInteg = 0;
  //
  if (fBeamEnergy<=0 && fBeamType!=kNoBeamField) {
    if      (fBeamType == kBeamTypepp) fBeamEnergy = 7000.; // max proton energy
    else if (fBeamType == kBeamTypeAA) fBeamEnergy = 2760;  // max PbPb energy
    else if (fBeamType == kBeamTypepA || fBeamType == kBeamTypeAp) fBeamEnergy = 2760;  // same rigitiy max PbPb energy
    AliInfo("Maximim possible beam energy for requested beam is assumed");
  } 
  const char* parname = 0;
  //  
  if      (fMapType == k2kG) parname = fDipoleOFF ? "Sol12_Dip0_Hole":"Sol12_Dip6_Hole";
  else if (fMapType == k5kG) parname = fDipoleOFF ? "Sol30_Dip0_Hole":"Sol30_Dip6_Hole";
  else if (fMapType == k5kGUniform) parname = "Sol30_Dip6_Uniform";
  else AliFatal(Form("Unknown field identifier %d is requested\n",fMapType));
  //
  SetDataFileName(path);
  SetParamName(parname);
  //
  LoadParameterization();
  InitMachineField(fBeamType,fBeamEnergy);
  double xyz[3]={0.,0.,0.};
  fSolenoid = GetBz(xyz);
  SetFactorSol(factorSol);
  SetFactorDip(factorDip);
  Print("a");
}

//_______________________________________________________________________
AliMagF::AliMagF(const AliMagF &src):
  TVirtualMagField(src),
  fMeasuredMap(0),
  fMapType(src.fMapType),
  fSolenoid(src.fSolenoid),
  fBeamType(src.fBeamType),
  fBeamEnergy(src.fBeamEnergy),
  fInteg(src.fInteg),
  fPrecInteg(src.fPrecInteg),
  fFactorSol(src.fFactorSol),
  fFactorDip(src.fFactorDip),
  fMax(src.fMax),
  fDipoleOFF(src.fDipoleOFF),
  fQuadGradient(src.fQuadGradient),
  fDipoleField(src.fDipoleField),
  fCCorrField(src.fCCorrField), 
  fACorr1Field(src.fACorr1Field),
  fACorr2Field(src.fACorr2Field),
  fParNames(src.fParNames)
{
  if (src.fMeasuredMap) fMeasuredMap = new AliMagWrapCheb(*src.fMeasuredMap);
}

//_______________________________________________________________________
AliMagF::~AliMagF()
{
  delete fMeasuredMap;
}

//_______________________________________________________________________
Bool_t AliMagF::LoadParameterization()
{
  if (fMeasuredMap) {
    AliFatal(Form("Field data %s are already loaded from %s\n",GetParamName(),GetDataFileName()));
  }
  //
  char* fname = gSystem->ExpandPathName(GetDataFileName());
  TFile* file = TFile::Open(fname);
  if (!file) {
    AliFatal(Form("Failed to open magnetic field data file %s\n",fname)); 
  }
  //
  fMeasuredMap = dynamic_cast<AliMagWrapCheb*>(file->Get(GetParamName()));
  if (!fMeasuredMap) {
    AliFatal(Form("Did not find field %s in %s\n",GetParamName(),fname)); 
  }
  file->Close();
  delete file;
  return kTRUE;
}


//_______________________________________________________________________
void AliMagF::Field(const Double_t *xyz, Double_t *b)
{
  // Method to calculate the field at point  xyz
  //
  //  b[0]=b[1]=b[2]=0.0;
  if (fMeasuredMap && xyz[2]>fMeasuredMap->GetMinZ() && xyz[2]<fMeasuredMap->GetMaxZ()) {
    fMeasuredMap->Field(xyz,b);
    if (xyz[2]>fgkSol2DipZ || fDipoleOFF) for (int i=3;i--;) b[i] *= fFactorSol;
    else                                  for (int i=3;i--;) b[i] *= fFactorDip;    
  }
  else MachineField(xyz, b);
  //
}

//_______________________________________________________________________
Double_t AliMagF::GetBz(const Double_t *xyz) const
{
  // Method to calculate the field at point  xyz
  //
  if (fMeasuredMap && xyz[2]>fMeasuredMap->GetMinZ() && xyz[2]<fMeasuredMap->GetMaxZ()) {
    double bz = fMeasuredMap->GetBz(xyz);
    return (xyz[2]>fgkSol2DipZ || fDipoleOFF) ? bz*fFactorSol : bz*fFactorDip;    
  }
  else return 0.;
}

//_______________________________________________________________________
AliMagF& AliMagF::operator=(const AliMagF& src)
{
  if (this != &src) {
    if (src.fMeasuredMap) { 
      if (fMeasuredMap) delete fMeasuredMap;
      fMeasuredMap = new AliMagWrapCheb(*src.fMeasuredMap);
    }
    SetName(src.GetName());
    fSolenoid    = src.fSolenoid;
    fBeamType    = src.fBeamType;
    fBeamEnergy  = src.fBeamEnergy;
    fInteg       = src.fInteg;
    fPrecInteg   = src.fPrecInteg;
    fFactorSol   = src.fFactorSol;
    fFactorDip   = src.fFactorDip;
    fMax         = src.fMax;
    fDipoleOFF   = src.fDipoleOFF;
    fParNames    = src.fParNames;
  }
  return *this;
}

//_______________________________________________________________________
void AliMagF::InitMachineField(BeamType_t btype, Double_t benergy)
{
  if (btype==kNoBeamField) {
    fQuadGradient = fDipoleField = fCCorrField = fACorr1Field = fACorr2Field = 0.;
    return;
  }
  //
  double rigScale = benergy/7000.;   // scale according to ratio of E/Enominal
  // for ions assume PbPb (with energy provided per nucleon) and account for A/Z
  if (btype==kBeamTypeAA/* || btype==kBeamTypepA || btype==kBeamTypeAp */) rigScale *= 208./82.;
  // Attention: in p-Pb the energy recorded in the GRP is the PROTON energy, no rigidity
  // rescaling is needed
  //
  fQuadGradient = 22.0002*rigScale;
  fDipoleField  = 37.8781*rigScale;
  //
  // SIDE C
  fCCorrField   = -9.6980;
  // SIDE A
  fACorr1Field  = -13.2247;
  fACorr2Field  =  11.7905;
  //
}

//_______________________________________________________________________
void AliMagF::MachineField(const Double_t *x, Double_t *b) const
{
  // ---- This is the ZDC part
  // Compansators for Alice Muon Arm Dipole
  const Double_t kBComp1CZ = 1075., kBComp1hDZ = 260./2., kBComp1SqR = 4.0*4.0; 
  const Double_t kBComp2CZ = 2049., kBComp2hDZ = 153./2., kBComp2SqR = 4.5*4.5; 
  //  
  const Double_t kTripQ1CZ = 2615., kTripQ1hDZ = 637./2., kTripQ1SqR = 3.5*3.5;
  const Double_t kTripQ2CZ = 3480., kTripQ2hDZ = 550./2., kTripQ2SqR = 3.5*3.5;
  const Double_t kTripQ3CZ = 4130., kTripQ3hDZ = 550./2., kTripQ3SqR = 3.5*3.5;
  const Double_t kTripQ4CZ = 5015., kTripQ4hDZ = 637./2., kTripQ4SqR = 3.5*3.5;
  //
  const Double_t kDip1CZ = 6310.8,  kDip1hDZ = 945./2., kDip1SqRC = 4.5*4.5, kDip1SqRA = 3.375*3.375;
  const Double_t kDip2CZ = 12640.3, kDip2hDZ = 945./2., kDip2SqRC = 4.5*4.5, kDip2SqRA = 3.75*3.75;
  const Double_t kDip2DXC = 9.7, kDip2DXA = 9.4;
  //
  double rad2 = x[0] * x[0] + x[1] * x[1];
  //
  b[0] = b[1] = b[2] = 0;
  //
  // SIDE C **************************************************
  if(x[2]<0.){  
    if(TMath::Abs(x[2]+kBComp2CZ)<kBComp2hDZ && rad2 < kBComp2SqR){
      b[0] = fCCorrField*fFactorDip;
    } 
    else if(TMath::Abs(x[2]+kTripQ1CZ)<kTripQ1hDZ && rad2 < kTripQ1SqR){
      b[0] = fQuadGradient*x[1];
      b[1] = fQuadGradient*x[0];
    }
    else if(TMath::Abs(x[2]+kTripQ2CZ)<kTripQ2hDZ && rad2 < kTripQ2SqR){
      b[0] = -fQuadGradient*x[1];
      b[1] = -fQuadGradient*x[0];
    }
    else if(TMath::Abs(x[2]+kTripQ3CZ)<kTripQ3hDZ && rad2 < kTripQ3SqR){
      b[0] = -fQuadGradient*x[1];
      b[1] = -fQuadGradient*x[0];
    }
    else if(TMath::Abs(x[2]+kTripQ4CZ)<kTripQ4hDZ && rad2 < kTripQ4SqR){
      b[0] = fQuadGradient*x[1];
      b[1] = fQuadGradient*x[0];
    }
    else if(TMath::Abs(x[2]+kDip1CZ)<kDip1hDZ && rad2 < kDip1SqRC){
      b[1] = fDipoleField;
    }
    else if(TMath::Abs(x[2]+kDip2CZ)<kDip2hDZ && rad2 < kDip2SqRC) {
      double dxabs = TMath::Abs(x[0])-kDip2DXC;
      if ( (dxabs*dxabs + x[1]*x[1])<kDip2SqRC) {
	b[1] = -fDipoleField;
      }
    }
  }
  //
  // SIDE A **************************************************
  else{        
    if(TMath::Abs(x[2]-kBComp1CZ)<kBComp1hDZ && rad2 < kBComp1SqR) {
      // Compensator magnet at z = 1075 m 
      b[0] = fACorr1Field*fFactorDip;
    }
    //
    if(TMath::Abs(x[2]-kBComp2CZ)<kBComp2hDZ && rad2 < kBComp2SqR){
      b[0] = fACorr2Field*fFactorDip;
    }
    else if(TMath::Abs(x[2]-kTripQ1CZ)<kTripQ1hDZ && rad2 < kTripQ1SqR){
      b[0] = -fQuadGradient*x[1];
      b[1] = -fQuadGradient*x[0];
    }
    else if(TMath::Abs(x[2]-kTripQ2CZ)<kTripQ2hDZ && rad2 < kTripQ2SqR){
      b[0] =  fQuadGradient*x[1];
      b[1] =  fQuadGradient*x[0];
    }
    else if(TMath::Abs(x[2]-kTripQ3CZ)<kTripQ3hDZ && rad2 < kTripQ3SqR){
      b[0] =  fQuadGradient*x[1];
      b[1] =  fQuadGradient*x[0];
    }
    else if(TMath::Abs(x[2]-kTripQ4CZ)<kTripQ4hDZ && rad2 < kTripQ4SqR){
      b[0] = -fQuadGradient*x[1];
      b[1] = -fQuadGradient*x[0];
    }
    else if(TMath::Abs(x[2]-kDip1CZ)<kDip1hDZ && rad2 < kDip1SqRA){
      b[1] = -fDipoleField;
    }
    else if(TMath::Abs(x[2]-kDip2CZ)<kDip2hDZ && rad2 < kDip2SqRA) {
      double dxabs = TMath::Abs(x[0])-kDip2DXA;
      if ( (dxabs*dxabs + x[1]*x[1])<kDip2SqRA) {
	b[1] = fDipoleField;
      }
    }
  }
  //
}

//_______________________________________________________________________
void AliMagF::GetTPCInt(const Double_t *xyz, Double_t *b) const
{
  // Method to calculate the integral_0^z of br,bt,bz 
  b[0]=b[1]=b[2]=0.0;
  if (fMeasuredMap) {
    fMeasuredMap->GetTPCInt(xyz,b);
    for (int i=3;i--;) b[i] *= fFactorSol;
  }
}

//_______________________________________________________________________
void AliMagF::GetTPCRatInt(const Double_t *xyz, Double_t *b) const
{
  // Method to calculate the integral_0^z of bx/bz,by/bz and (bx/bz)^2+(by/bz)^2
  b[0]=b[1]=b[2]=0.0;
  if (fMeasuredMap) {
    fMeasuredMap->GetTPCRatInt(xyz,b);
    b[2] /= 100;
  }
}

//_______________________________________________________________________
void AliMagF::GetTPCIntCyl(const Double_t *rphiz, Double_t *b) const
{
  // Method to calculate the integral_0^z of br,bt,bz 
  // in cylindrical coordiates ( -pi<phi<pi convention )
  b[0]=b[1]=b[2]=0.0;
  if (fMeasuredMap) {
    fMeasuredMap->GetTPCIntCyl(rphiz,b);
    for (int i=3;i--;) b[i] *= fFactorSol;
  }
}

//_______________________________________________________________________
void AliMagF::GetTPCRatIntCyl(const Double_t *rphiz, Double_t *b) const
{
  // Method to calculate the integral_0^z of bx/bz,by/bz and (bx/bz)^2+(by/bz)^2
  // in cylindrical coordiates ( -pi<phi<pi convention )
  b[0]=b[1]=b[2]=0.0;
  if (fMeasuredMap) {
    fMeasuredMap->GetTPCRatIntCyl(rphiz,b);
    b[2] /= 100;
  }
}

//_______________________________________________________________________
void AliMagF::SetFactorSol(Float_t fc)
{
  // set the sign/scale of the current in the L3 according to fgkPolarityConvention
  switch (fgkPolarityConvention) {
  case kConvDCS2008: fFactorSol = -fc; break;
  case kConvLHC    : fFactorSol = -fc; break;
  default          : fFactorSol =  fc; break;  // case kConvMap2005: fFactorSol =  fc; break;
  }
}

//_______________________________________________________________________
void AliMagF::SetFactorDip(Float_t fc)
{
  // set the sign*scale of the current in the Dipole according to fgkPolarityConvention
  switch (fgkPolarityConvention) {
  case kConvDCS2008: fFactorDip =  fc; break;
  case kConvLHC    : fFactorDip = -fc; break;
  default          : fFactorDip =  fc; break;  // case kConvMap2005: fFactorDip =  fc; break;
  }
}

//_______________________________________________________________________
Double_t AliMagF::GetFactorSol() const
{
  // return the sign*scale of the current in the Dipole according to fgkPolarityConventionthe 
  switch (fgkPolarityConvention) {
  case kConvDCS2008: return -fFactorSol;
  case kConvLHC    : return -fFactorSol;
  default          : return  fFactorSol;       //  case kConvMap2005: return  fFactorSol;
  }
}

//_______________________________________________________________________
Double_t AliMagF::GetFactorDip() const
{
  // return the sign*scale of the current in the Dipole according to fgkPolarityConventionthe 
  switch (fgkPolarityConvention) {
  case kConvDCS2008: return  fFactorDip;
  case kConvLHC    : return -fFactorDip;
  default          : return  fFactorDip;       //  case kConvMap2005: return  fFactorDip;
  }
}

//_____________________________________________________________________________
AliMagF* AliMagF::CreateFieldMap(Float_t l3Cur, Float_t diCur, Int_t convention, Bool_t uniform,
				 Float_t beamenergy, const Char_t *beamtype, const Char_t *path) 
{
  //------------------------------------------------
  // The magnetic field map, defined externally...
  // L3 current 30000 A  -> 0.5 T
  // L3 current 12000 A  -> 0.2 T
  // dipole current 6000 A
  // The polarities must match the convention (LHC or DCS2008) 
  // unless the special uniform map was used for MC
  //------------------------------------------------
  const Float_t l3NominalCurrent1=30000.; // (A)
  const Float_t l3NominalCurrent2=12000.; // (A)
  const Float_t diNominalCurrent =6000. ; // (A)

  const Float_t tolerance=0.03; // relative current tolerance
  const Float_t zero=77.;       // "zero" current (A)
  //
  BMap_t map = k5kG;
  double sclL3,sclDip;
  //
  Float_t l3Pol = l3Cur > 0 ? 1:-1;
  Float_t diPol = diCur > 0 ? 1:-1;
 
  l3Cur = TMath::Abs(l3Cur);
  diCur = TMath::Abs(diCur);
  //
  if (TMath::Abs((sclDip=diCur/diNominalCurrent)-1.) > tolerance && !uniform) {
    if (diCur <= zero) sclDip = 0.; // some small current.. -> Dipole OFF
    else {
      AliFatalGeneral("AliMagF",Form("Wrong dipole current (%f A)!",diCur));
    }
  }
  //
  if (uniform) { 
    // special treatment of special MC with uniform mag field (normalized to 0.5 T)
    // no check for scaling/polarities are done
    map   = k5kGUniform;
    sclL3 = l3Cur/l3NominalCurrent1; 
  }
  else {
    if      (TMath::Abs((sclL3=l3Cur/l3NominalCurrent1)-1.) < tolerance) map  = k5kG;
    else if (TMath::Abs((sclL3=l3Cur/l3NominalCurrent2)-1.) < tolerance) map  = k2kG;
    else if (l3Cur <= zero && diCur<=zero)   { sclL3=0; sclDip=0; map  = k5kGUniform;}
    else {
      AliFatalGeneral("AliMagF",Form("Wrong L3 current (%f A)!",l3Cur));
    }
  }
  //
  if (sclDip!=0 && map!=k5kGUniform) {
    if ( (l3Cur<=zero) || ((convention==kConvLHC && l3Pol!=diPol) || (convention==kConvDCS2008 && l3Pol==diPol)) ) { 
      AliFatalGeneral("AliMagF",Form("Wrong combination for L3/Dipole polarities (%c/%c) for convention %d",
				     l3Pol>0?'+':'-',diPol>0?'+':'-',GetPolarityConvention()));
    }
  }
  //
  if (l3Pol<0) sclL3  = -sclL3;
  if (diPol<0) sclDip = -sclDip;
  //
  BeamType_t btype = kNoBeamField;
  TString btypestr = beamtype;
  btypestr.ToLower();
  TPRegexp protonBeam("(proton|p)\\s*-?\\s*\\1");
  TPRegexp ionBeam("(lead|pb|ion|a|A)\\s*-?\\s*\\1");
  TPRegexp protonionBeam("(proton|p)\\s*-?\\s*(lead|pb|ion|a|A)");
  TPRegexp ionprotonBeam("(lead|pb|ion|a|A)\\s*-?\\s*(proton|p)");
  if (btypestr.Contains(ionBeam)) btype = kBeamTypeAA;
  else if (btypestr.Contains(protonBeam)) btype = kBeamTypepp;
  else if (btypestr.Contains(protonionBeam)) btype = kBeamTypepA;
  else if (btypestr.Contains(ionprotonBeam)) btype = kBeamTypeAp;
  else AliInfoGeneral("AliMagF",Form("Assume no LHC magnet field for the beam type %s, ",beamtype));
  char ttl[80];
  snprintf(ttl,79,"L3: %+5d Dip: %+4d kA; %s | Polarities in %s convention",(int)TMath::Sign(l3Cur,float(sclL3)),
	  (int)TMath::Sign(diCur,float(sclDip)),uniform ? " Constant":"",
	  convention==kConvLHC ? "LHC":"DCS2008");
  // LHC and DCS08 conventions have opposite dipole polarities
  if ( GetPolarityConvention() != convention) sclDip = -sclDip;
  //
  return new AliMagF("MagneticFieldMap", ttl,sclL3,sclDip,map,btype,beamenergy,2,10.,path);
  //
}

//_____________________________________________________________________________
const char*  AliMagF::GetBeamTypeText() const
{
  // beam type in text form
  const char *beamNA  = "No Beam";
  const char *beamPP  = "p-p";
  const char *beamPbPb= "A-A";
  const char *beamPPb = "p-A";
  const char *beamPbP = "A-p";
  switch ( fBeamType ) {
  case kBeamTypepp : return beamPP;
  case kBeamTypeAA : return beamPbPb;
  case kBeamTypepA : return beamPPb;
  case kBeamTypeAp : return beamPbP;
  case kNoBeamField: 
  default:           return beamNA;
  }
}

//_____________________________________________________________________________
void AliMagF::Print(Option_t *opt) const
{
  // print short or long info
  TString opts = opt; opts.ToLower();
  AliInfo(Form("%s:%s",GetName(),GetTitle()));
  AliInfo(Form("Solenoid (%+.2f*)%.0f kG, Dipole %s (%+.2f) %s",
	       GetFactorSol(),(fMapType==k5kG||fMapType==k5kGUniform)?5.:2.,
	       fDipoleOFF ? "OFF":"ON",GetFactorDip(),fMapType==k5kGUniform?" |Constant Field!":""));
  if (opts.Contains("a")) {
    AliInfo(Form("Machine B fields for %s beam (%.0f GeV): QGrad: %.4f Dipole: %.4f",
		 GetBeamTypeText(),
		 fBeamEnergy,fQuadGradient,fDipoleField));
    AliInfo(Form("Uses %s of %s",GetParamName(),GetDataFileName()));
  }
}
 AliMagF.cxx:1
 AliMagF.cxx:2
 AliMagF.cxx:3
 AliMagF.cxx:4
 AliMagF.cxx:5
 AliMagF.cxx:6
 AliMagF.cxx:7
 AliMagF.cxx:8
 AliMagF.cxx:9
 AliMagF.cxx:10
 AliMagF.cxx:11
 AliMagF.cxx:12
 AliMagF.cxx:13
 AliMagF.cxx:14
 AliMagF.cxx:15
 AliMagF.cxx:16
 AliMagF.cxx:17
 AliMagF.cxx:18
 AliMagF.cxx:19
 AliMagF.cxx:20
 AliMagF.cxx:21
 AliMagF.cxx:22
 AliMagF.cxx:23
 AliMagF.cxx:24
 AliMagF.cxx:25
 AliMagF.cxx:26
 AliMagF.cxx:27
 AliMagF.cxx:28
 AliMagF.cxx:29
 AliMagF.cxx:30
 AliMagF.cxx:31
 AliMagF.cxx:32
 AliMagF.cxx:33
 AliMagF.cxx:34
 AliMagF.cxx:35
 AliMagF.cxx:36
 AliMagF.cxx:37
 AliMagF.cxx:38
 AliMagF.cxx:39
 AliMagF.cxx:40
 AliMagF.cxx:41
 AliMagF.cxx:42
 AliMagF.cxx:43
 AliMagF.cxx:44
 AliMagF.cxx:45
 AliMagF.cxx:46
 AliMagF.cxx:47
 AliMagF.cxx:48
 AliMagF.cxx:49
 AliMagF.cxx:50
 AliMagF.cxx:51
 AliMagF.cxx:52
 AliMagF.cxx:53
 AliMagF.cxx:54
 AliMagF.cxx:55
 AliMagF.cxx:56
 AliMagF.cxx:57
 AliMagF.cxx:58
 AliMagF.cxx:59
 AliMagF.cxx:60
 AliMagF.cxx:61
 AliMagF.cxx:62
 AliMagF.cxx:63
 AliMagF.cxx:64
 AliMagF.cxx:65
 AliMagF.cxx:66
 AliMagF.cxx:67
 AliMagF.cxx:68
 AliMagF.cxx:69
 AliMagF.cxx:70
 AliMagF.cxx:71
 AliMagF.cxx:72
 AliMagF.cxx:73
 AliMagF.cxx:74
 AliMagF.cxx:75
 AliMagF.cxx:76
 AliMagF.cxx:77
 AliMagF.cxx:78
 AliMagF.cxx:79
 AliMagF.cxx:80
 AliMagF.cxx:81
 AliMagF.cxx:82
 AliMagF.cxx:83
 AliMagF.cxx:84
 AliMagF.cxx:85
 AliMagF.cxx:86
 AliMagF.cxx:87
 AliMagF.cxx:88
 AliMagF.cxx:89
 AliMagF.cxx:90
 AliMagF.cxx:91
 AliMagF.cxx:92
 AliMagF.cxx:93
 AliMagF.cxx:94
 AliMagF.cxx:95
 AliMagF.cxx:96
 AliMagF.cxx:97
 AliMagF.cxx:98
 AliMagF.cxx:99
 AliMagF.cxx:100
 AliMagF.cxx:101
 AliMagF.cxx:102
 AliMagF.cxx:103
 AliMagF.cxx:104
 AliMagF.cxx:105
 AliMagF.cxx:106
 AliMagF.cxx:107
 AliMagF.cxx:108
 AliMagF.cxx:109
 AliMagF.cxx:110
 AliMagF.cxx:111
 AliMagF.cxx:112
 AliMagF.cxx:113
 AliMagF.cxx:114
 AliMagF.cxx:115
 AliMagF.cxx:116
 AliMagF.cxx:117
 AliMagF.cxx:118
 AliMagF.cxx:119
 AliMagF.cxx:120
 AliMagF.cxx:121
 AliMagF.cxx:122
 AliMagF.cxx:123
 AliMagF.cxx:124
 AliMagF.cxx:125
 AliMagF.cxx:126
 AliMagF.cxx:127
 AliMagF.cxx:128
 AliMagF.cxx:129
 AliMagF.cxx:130
 AliMagF.cxx:131
 AliMagF.cxx:132
 AliMagF.cxx:133
 AliMagF.cxx:134
 AliMagF.cxx:135
 AliMagF.cxx:136
 AliMagF.cxx:137
 AliMagF.cxx:138
 AliMagF.cxx:139
 AliMagF.cxx:140
 AliMagF.cxx:141
 AliMagF.cxx:142
 AliMagF.cxx:143
 AliMagF.cxx:144
 AliMagF.cxx:145
 AliMagF.cxx:146
 AliMagF.cxx:147
 AliMagF.cxx:148
 AliMagF.cxx:149
 AliMagF.cxx:150
 AliMagF.cxx:151
 AliMagF.cxx:152
 AliMagF.cxx:153
 AliMagF.cxx:154
 AliMagF.cxx:155
 AliMagF.cxx:156
 AliMagF.cxx:157
 AliMagF.cxx:158
 AliMagF.cxx:159
 AliMagF.cxx:160
 AliMagF.cxx:161
 AliMagF.cxx:162
 AliMagF.cxx:163
 AliMagF.cxx:164
 AliMagF.cxx:165
 AliMagF.cxx:166
 AliMagF.cxx:167
 AliMagF.cxx:168
 AliMagF.cxx:169
 AliMagF.cxx:170
 AliMagF.cxx:171
 AliMagF.cxx:172
 AliMagF.cxx:173
 AliMagF.cxx:174
 AliMagF.cxx:175
 AliMagF.cxx:176
 AliMagF.cxx:177
 AliMagF.cxx:178
 AliMagF.cxx:179
 AliMagF.cxx:180
 AliMagF.cxx:181
 AliMagF.cxx:182
 AliMagF.cxx:183
 AliMagF.cxx:184
 AliMagF.cxx:185
 AliMagF.cxx:186
 AliMagF.cxx:187
 AliMagF.cxx:188
 AliMagF.cxx:189
 AliMagF.cxx:190
 AliMagF.cxx:191
 AliMagF.cxx:192
 AliMagF.cxx:193
 AliMagF.cxx:194
 AliMagF.cxx:195
 AliMagF.cxx:196
 AliMagF.cxx:197
 AliMagF.cxx:198
 AliMagF.cxx:199
 AliMagF.cxx:200
 AliMagF.cxx:201
 AliMagF.cxx:202
 AliMagF.cxx:203
 AliMagF.cxx:204
 AliMagF.cxx:205
 AliMagF.cxx:206
 AliMagF.cxx:207
 AliMagF.cxx:208
 AliMagF.cxx:209
 AliMagF.cxx:210
 AliMagF.cxx:211
 AliMagF.cxx:212
 AliMagF.cxx:213
 AliMagF.cxx:214
 AliMagF.cxx:215
 AliMagF.cxx:216
 AliMagF.cxx:217
 AliMagF.cxx:218
 AliMagF.cxx:219
 AliMagF.cxx:220
 AliMagF.cxx:221
 AliMagF.cxx:222
 AliMagF.cxx:223
 AliMagF.cxx:224
 AliMagF.cxx:225
 AliMagF.cxx:226
 AliMagF.cxx:227
 AliMagF.cxx:228
 AliMagF.cxx:229
 AliMagF.cxx:230
 AliMagF.cxx:231
 AliMagF.cxx:232
 AliMagF.cxx:233
 AliMagF.cxx:234
 AliMagF.cxx:235
 AliMagF.cxx:236
 AliMagF.cxx:237
 AliMagF.cxx:238
 AliMagF.cxx:239
 AliMagF.cxx:240
 AliMagF.cxx:241
 AliMagF.cxx:242
 AliMagF.cxx:243
 AliMagF.cxx:244
 AliMagF.cxx:245
 AliMagF.cxx:246
 AliMagF.cxx:247
 AliMagF.cxx:248
 AliMagF.cxx:249
 AliMagF.cxx:250
 AliMagF.cxx:251
 AliMagF.cxx:252
 AliMagF.cxx:253
 AliMagF.cxx:254
 AliMagF.cxx:255
 AliMagF.cxx:256
 AliMagF.cxx:257
 AliMagF.cxx:258
 AliMagF.cxx:259
 AliMagF.cxx:260
 AliMagF.cxx:261
 AliMagF.cxx:262
 AliMagF.cxx:263
 AliMagF.cxx:264
 AliMagF.cxx:265
 AliMagF.cxx:266
 AliMagF.cxx:267
 AliMagF.cxx:268
 AliMagF.cxx:269
 AliMagF.cxx:270
 AliMagF.cxx:271
 AliMagF.cxx:272
 AliMagF.cxx:273
 AliMagF.cxx:274
 AliMagF.cxx:275
 AliMagF.cxx:276
 AliMagF.cxx:277
 AliMagF.cxx:278
 AliMagF.cxx:279
 AliMagF.cxx:280
 AliMagF.cxx:281
 AliMagF.cxx:282
 AliMagF.cxx:283
 AliMagF.cxx:284
 AliMagF.cxx:285
 AliMagF.cxx:286
 AliMagF.cxx:287
 AliMagF.cxx:288
 AliMagF.cxx:289
 AliMagF.cxx:290
 AliMagF.cxx:291
 AliMagF.cxx:292
 AliMagF.cxx:293
 AliMagF.cxx:294
 AliMagF.cxx:295
 AliMagF.cxx:296
 AliMagF.cxx:297
 AliMagF.cxx:298
 AliMagF.cxx:299
 AliMagF.cxx:300
 AliMagF.cxx:301
 AliMagF.cxx:302
 AliMagF.cxx:303
 AliMagF.cxx:304
 AliMagF.cxx:305
 AliMagF.cxx:306
 AliMagF.cxx:307
 AliMagF.cxx:308
 AliMagF.cxx:309
 AliMagF.cxx:310
 AliMagF.cxx:311
 AliMagF.cxx:312
 AliMagF.cxx:313
 AliMagF.cxx:314
 AliMagF.cxx:315
 AliMagF.cxx:316
 AliMagF.cxx:317
 AliMagF.cxx:318
 AliMagF.cxx:319
 AliMagF.cxx:320
 AliMagF.cxx:321
 AliMagF.cxx:322
 AliMagF.cxx:323
 AliMagF.cxx:324
 AliMagF.cxx:325
 AliMagF.cxx:326
 AliMagF.cxx:327
 AliMagF.cxx:328
 AliMagF.cxx:329
 AliMagF.cxx:330
 AliMagF.cxx:331
 AliMagF.cxx:332
 AliMagF.cxx:333
 AliMagF.cxx:334
 AliMagF.cxx:335
 AliMagF.cxx:336
 AliMagF.cxx:337
 AliMagF.cxx:338
 AliMagF.cxx:339
 AliMagF.cxx:340
 AliMagF.cxx:341
 AliMagF.cxx:342
 AliMagF.cxx:343
 AliMagF.cxx:344
 AliMagF.cxx:345
 AliMagF.cxx:346
 AliMagF.cxx:347
 AliMagF.cxx:348
 AliMagF.cxx:349
 AliMagF.cxx:350
 AliMagF.cxx:351
 AliMagF.cxx:352
 AliMagF.cxx:353
 AliMagF.cxx:354
 AliMagF.cxx:355
 AliMagF.cxx:356
 AliMagF.cxx:357
 AliMagF.cxx:358
 AliMagF.cxx:359
 AliMagF.cxx:360
 AliMagF.cxx:361
 AliMagF.cxx:362
 AliMagF.cxx:363
 AliMagF.cxx:364
 AliMagF.cxx:365
 AliMagF.cxx:366
 AliMagF.cxx:367
 AliMagF.cxx:368
 AliMagF.cxx:369
 AliMagF.cxx:370
 AliMagF.cxx:371
 AliMagF.cxx:372
 AliMagF.cxx:373
 AliMagF.cxx:374
 AliMagF.cxx:375
 AliMagF.cxx:376
 AliMagF.cxx:377
 AliMagF.cxx:378
 AliMagF.cxx:379
 AliMagF.cxx:380
 AliMagF.cxx:381
 AliMagF.cxx:382
 AliMagF.cxx:383
 AliMagF.cxx:384
 AliMagF.cxx:385
 AliMagF.cxx:386
 AliMagF.cxx:387
 AliMagF.cxx:388
 AliMagF.cxx:389
 AliMagF.cxx:390
 AliMagF.cxx:391
 AliMagF.cxx:392
 AliMagF.cxx:393
 AliMagF.cxx:394
 AliMagF.cxx:395
 AliMagF.cxx:396
 AliMagF.cxx:397
 AliMagF.cxx:398
 AliMagF.cxx:399
 AliMagF.cxx:400
 AliMagF.cxx:401
 AliMagF.cxx:402
 AliMagF.cxx:403
 AliMagF.cxx:404
 AliMagF.cxx:405
 AliMagF.cxx:406
 AliMagF.cxx:407
 AliMagF.cxx:408
 AliMagF.cxx:409
 AliMagF.cxx:410
 AliMagF.cxx:411
 AliMagF.cxx:412
 AliMagF.cxx:413
 AliMagF.cxx:414
 AliMagF.cxx:415
 AliMagF.cxx:416
 AliMagF.cxx:417
 AliMagF.cxx:418
 AliMagF.cxx:419
 AliMagF.cxx:420
 AliMagF.cxx:421
 AliMagF.cxx:422
 AliMagF.cxx:423
 AliMagF.cxx:424
 AliMagF.cxx:425
 AliMagF.cxx:426
 AliMagF.cxx:427
 AliMagF.cxx:428
 AliMagF.cxx:429
 AliMagF.cxx:430
 AliMagF.cxx:431
 AliMagF.cxx:432
 AliMagF.cxx:433
 AliMagF.cxx:434
 AliMagF.cxx:435
 AliMagF.cxx:436
 AliMagF.cxx:437
 AliMagF.cxx:438
 AliMagF.cxx:439
 AliMagF.cxx:440
 AliMagF.cxx:441
 AliMagF.cxx:442
 AliMagF.cxx:443
 AliMagF.cxx:444
 AliMagF.cxx:445
 AliMagF.cxx:446
 AliMagF.cxx:447
 AliMagF.cxx:448
 AliMagF.cxx:449
 AliMagF.cxx:450
 AliMagF.cxx:451
 AliMagF.cxx:452
 AliMagF.cxx:453
 AliMagF.cxx:454
 AliMagF.cxx:455
 AliMagF.cxx:456
 AliMagF.cxx:457
 AliMagF.cxx:458
 AliMagF.cxx:459
 AliMagF.cxx:460
 AliMagF.cxx:461
 AliMagF.cxx:462
 AliMagF.cxx:463
 AliMagF.cxx:464
 AliMagF.cxx:465
 AliMagF.cxx:466
 AliMagF.cxx:467
 AliMagF.cxx:468
 AliMagF.cxx:469
 AliMagF.cxx:470
 AliMagF.cxx:471
 AliMagF.cxx:472
 AliMagF.cxx:473
 AliMagF.cxx:474
 AliMagF.cxx:475
 AliMagF.cxx:476
 AliMagF.cxx:477
 AliMagF.cxx:478
 AliMagF.cxx:479
 AliMagF.cxx:480
 AliMagF.cxx:481
 AliMagF.cxx:482
 AliMagF.cxx:483
 AliMagF.cxx:484
 AliMagF.cxx:485
 AliMagF.cxx:486
 AliMagF.cxx:487
 AliMagF.cxx:488
 AliMagF.cxx:489
 AliMagF.cxx:490
 AliMagF.cxx:491
 AliMagF.cxx:492
 AliMagF.cxx:493
 AliMagF.cxx:494
 AliMagF.cxx:495
 AliMagF.cxx:496
 AliMagF.cxx:497
 AliMagF.cxx:498
 AliMagF.cxx:499
 AliMagF.cxx:500
 AliMagF.cxx:501
 AliMagF.cxx:502
 AliMagF.cxx:503
 AliMagF.cxx:504
 AliMagF.cxx:505
 AliMagF.cxx:506
 AliMagF.cxx:507
 AliMagF.cxx:508
 AliMagF.cxx:509
 AliMagF.cxx:510
 AliMagF.cxx:511
 AliMagF.cxx:512
 AliMagF.cxx:513
 AliMagF.cxx:514
 AliMagF.cxx:515
 AliMagF.cxx:516
 AliMagF.cxx:517
 AliMagF.cxx:518
 AliMagF.cxx:519
 AliMagF.cxx:520
 AliMagF.cxx:521
 AliMagF.cxx:522
 AliMagF.cxx:523
 AliMagF.cxx:524
 AliMagF.cxx:525
 AliMagF.cxx:526
 AliMagF.cxx:527
 AliMagF.cxx:528
 AliMagF.cxx:529
 AliMagF.cxx:530
 AliMagF.cxx:531
 AliMagF.cxx:532
 AliMagF.cxx:533
 AliMagF.cxx:534
 AliMagF.cxx:535
 AliMagF.cxx:536
 AliMagF.cxx:537
 AliMagF.cxx:538
 AliMagF.cxx:539
 AliMagF.cxx:540
 AliMagF.cxx:541
 AliMagF.cxx:542
 AliMagF.cxx:543
 AliMagF.cxx:544
 AliMagF.cxx:545
 AliMagF.cxx:546
 AliMagF.cxx:547
 AliMagF.cxx:548
 AliMagF.cxx:549
 AliMagF.cxx:550
 AliMagF.cxx:551
 AliMagF.cxx:552
 AliMagF.cxx:553
 AliMagF.cxx:554
 AliMagF.cxx:555
 AliMagF.cxx:556
 AliMagF.cxx:557
 AliMagF.cxx:558
 AliMagF.cxx:559
 AliMagF.cxx:560
 AliMagF.cxx:561
 AliMagF.cxx:562
 AliMagF.cxx:563
 AliMagF.cxx:564
 AliMagF.cxx:565
 AliMagF.cxx:566
 AliMagF.cxx:567
 AliMagF.cxx:568
 AliMagF.cxx:569
 AliMagF.cxx:570
 AliMagF.cxx:571
 AliMagF.cxx:572
 AliMagF.cxx:573
 AliMagF.cxx:574
 AliMagF.cxx:575
 AliMagF.cxx:576
 AliMagF.cxx:577
 AliMagF.cxx:578
 AliMagF.cxx:579
 AliMagF.cxx:580