KVElementDensity* KVElementDensityTable::FindElementBySymbol(const Char_t* X) const
{
   // Search table for an element with the given symbol. Case-insensitive.
   TString x = X;
   x.ToUpper();
   TIter next(tobj);
   KVElementDensity* elem;
   while ((elem = (KVElementDensity*)next())) {
      TString el = elem->GetElementSymbol();
      el.ToUpper();
      if (x == el) return elem;
   }
   return 0x0;
}
void KVRangeYanez::AddElementalMaterial(Int_t z, Int_t a)
{
   // Adds a material composed of a single isotope of a chemical element.
   // If the isotope (a) is not specified, we create a material containing the naturally
   // occuring isotopes of the given element, weighted according to their abundance.
   // If the mass is given, the material symbol will be "AX" where X is the symbol for the element
   //    e.g. "48Ca",  "124Sn", etc.
   // and the material name will be "Xxx-A" where Xxx is the name of the element
   //    e.g. "Calcium-48", "Tin-124", etc.
   // Otherwise, we just use the element symbol and name for naturally-occurring
   // mixtures of atomic elements ("Ca", "Calcium", etc.).

   KVIonRangeTableMaterial* mat;
   if (!a) {
      mat = MakeNaturallyOccuringElementMixture(z);
   } else {
      if (!gNDTManager) {
         Error("AddElementalMaterial",
               "Nuclear data tables have not been initialised");
         return;
      }
      KVElementDensity* ed = (KVElementDensity*)gNDTManager->GetData(z, a, "ElementDensity");
      if (!ed) {
         Error("AddElementalMaterial",
               "No element found in ElementDensity NDT-table with Z=%d", z);
         return;
      }
      TString state = "solid";
      if (ed->IsGas()) state = "gas";
      mat = new KVRangeYanezMaterial(this, Form("%s-%d", ed->GetElementName(), a),
                                     Form("%d%s", a, ed->GetElementSymbol()),
                                     state, ed->GetValue(), z, a);
      mat->Initialize();
   }
   CheckMaterialsList();
   fMaterials->Add(mat);
   mat->ls();
}
KVIonRangeTableMaterial::KVIonRangeTableMaterial(const KVIonRangeTable* tab, const Char_t* name, const Char_t* symbol,
      const Char_t* state, Double_t density, Double_t Z, Double_t A)
   : KVBase(name, symbol),
     fTable(tab),
     fState(state),
     fComposition(0),
     fCompound(kFALSE),
     fMixture(kFALSE),
     fDens(density),
     fZmat(Z),
     fAmat(A),
     fMoleWt(0),
     fDeltaE(0),
     fEres(0),
     fRange(0),
     fStopping(0)
{
   // Create new material with given (long) name and symbol
   //        symbol convention: for elements, use element symbol. for compounds, use chemical formula.
   //        e.g. silicon:    name="Silicon"  symbol="Si"
   //              C4H10:     name="Isobutane",  symbol="C4H10"
   // state="solid", "liquid", "gas"
   //
   // Density [g/cm**3] must be given for solid compounds/mixtures.
   // Densities of atomic elements are known (gNDTManager->GetValue(z, a, "ElementDensity")), they
   // will be used automatically, unless a different value is given here.
   // Densities of gases are calculated from the molar weight, temperature and pressure.

   if (Z > 0 && density < 0) {
      KVElementDensity* ed = (KVElementDensity*)gNDTManager->GetData(Z, A, "ElementDensity");
      if (!ed) {
         Warning("KVIonRangeTableMaterial",
                 "No element found in density table with Z=%f, density unknown", Z);
      }
      else
         fDens = ed->GetValue();
   }
}
KVIonRangeTableMaterial* KVRangeYanez::MakeNaturallyOccuringElementMixture(Int_t z)
{
   // create a material containing the naturally occuring isotopes of the given element,
   // weighted according to their abundance.

   if (!gNDTManager) {
      Error("MakeNaturallyOccuringElementMixture",
            "Nuclear data tables have not been initialised");
      return NULL;
   }
   KVElementDensity* ed = (KVElementDensity*)gNDTManager->GetData(z, z, "ElementDensity");
   if (!ed) {
      Error("AddElementalMaterial",
            "No element found in ElementDensity NDT-table with Z=%d", z);
      return 0x0;
   }
   TString state = "solid";
   if (ed->IsGas()) state = "gas";
   KVRangeYanezMaterial* mat =
      new KVRangeYanezMaterial(this,
                               ed->GetElementName(),
                               ed->GetElementSymbol(),
                               state, ed->GetValue());
   KVNucleus nuc(z);
   KVNumberList isotopes = nuc.GetKnownARange();
   isotopes.Begin();
   while (!isotopes.End()) {

      nuc.SetA(isotopes.Next());
      Double_t abundance = nuc.GetAbundance() / 100.;
      if (abundance > 0.) mat->AddMixtureElement(z, nuc.GetA(), 1, abundance);

   }
   mat->Initialize();
   return (KVIonRangeTableMaterial*)mat;
}
void KVElementDensityTable::Initialize()
{

   TString dfile;
   dfile.Form("%s.DataFile", GetName());
   TString cl_path;
   if (!KVBase::SearchKVFile(gEnv->GetValue(dfile.Data(), ""), cl_path, "data")) {
      Error("Initialize", "No file found for %s", GetName());
      return;
   }
   else {
//    Info("Initialize","%s will be read",gEnv->GetValue(dfile.Data(),""));
   }
   SetTitle(gEnv->GetValue(dfile.Data(), ""));

   Int_t ntot = 0;
   nucMap = new TMap(50, 2);
   KVFileReader* fr = new KVFileReader();
   fr->OpenFileToRead(cl_path.Data());

   //Premier passage
   //Lecture du nombre de noyaux a enregistrer
   while (fr->IsOK()) {

      fr->ReadLine(" \t");
      if (fr->GetCurrentLine().IsNull()) {
         break;
      }
      else if (fr->GetNparRead() == 0) {
         break;
      }
      else if (fr->GetReadPar(0).BeginsWith("//")) {

         kcomments += fr->GetCurrentLine();
         kcomments += "\n";

      }
      else {
         Int_t zz = fr->GetIntReadPar(4);
         Int_t aa = 2 * zz + 1;
         GiveIndexToNucleus(zz, aa, ntot);
         ntot += 1;
      }
   }

   if (!fr->PreparForReadingAgain()) return;

// Info("Initialize","Set up map for %d nuclei", ntot);
   CreateTable(ntot);

   KVElementDensity* lf = 0;
   ntot = 0;
   while (fr->IsOK()) {
      fr->ReadLine(" \t");
      if (fr->GetCurrentLine().IsNull()) {
         break;
      }
      else if (fr->GetNparRead() == 0) {
         break;
      }
      else if (fr->GetReadPar(0).BeginsWith("//")) { }
      else {
         CreateElement(ntot);
         lf = (KVElementDensity*)GetCurrent();

         KVString unit = fr->GetReadPar(1);
         Double_t units = KVUnits::g / KVUnits::cc;
         if (unit == "g/L") {
            lf->SetIsGas();
            units = KVUnits::g / KVUnits::litre;
         }
         Double_t val = fr->GetDoubleReadPar(0);
         lf->SetValue(val * units);
         lf->SetElementSymbol(fr->GetReadPar(3));
         lf->SetElementName(fr->GetReadPar(2));
         lf->SetZ(fr->GetIntReadPar(4));
         ntot += 1;
      }

   }

// Info("Initialize","table initialised correctly for %d/%d nuclei", ntot,GetNumberOfNuclei());
   fr->CloseFile();
   delete fr;

}