Skip to content

File NPInputParser.cxx

File List > core > NPInputParser.cxx

Go to the documentation of this file

#include "NPInputParser.h"
#include "NPException.h"
#include "NPFunction.h"
#include "NPSystemOfUnits.h"
#include <algorithm>
#include <fstream>
#include <iostream>
#include <sstream>
nptool::BlockPtr nptool::InputBlock::Copy() {
  auto res = std::make_shared<nptool::InputBlock>();
  res->m_Level = this->m_Level;
  res->m_MainToken = this->m_MainToken;
  res->m_MainValue = this->m_MainValue;
  res->m_Token = this->m_Token;
  res->m_Value = this->m_Value;
  return res;
}
std::vector<nptool::BlockPtr> nptool::InputBlock::GetSubBlock(std::string Token) {
  std::vector<nptool::BlockPtr> res;
  for (auto it = m_SubBlock.begin(), end = m_SubBlock.end(); it != end; it++) {
    if ((*it)->GetMainToken() == Token) {
      res.push_back(*it);
    }
  }
  return res;
}
std::string nptool::StripSpaces(std::string line) {
  // Remove preceding spaces
  while (*line.begin() == ' ')
    line = line.substr(1, line.length());

  // Remove trailing spaces
  if (line.length() > 0)
    while (*line.rbegin() == ' ')
      line = line.substr(0, line.length() - 1);

  // Remove preceding tabs
  while (*line.begin() == '\t')
    line = line.substr(1, line.length());

  // Remove trailing tabs
  if (line.length() > 0)
    while (*line.rbegin() == '\t')
      line = line.substr(0, line.length() - 1);

  return line;
}
unsigned int nptool::GetLevel(std::string line) {
  unsigned int level = 0;
  if (line.length() == 0)
    return 1000;

  for (unsigned int i = 0; i < line.length(); i++) {
    if (line.compare(i, 1, " ") == 0)
      level++;
    else
      break;
  }

  return level;
}

std::string nptool::ToLower(std::string line) {
  std::transform(line.begin(), line.end(), line.begin(), ::tolower);
  return line;
}

nptool::InputBlock::InputBlock(std::string line) {
  m_Level = GetLevel(line);
  m_MainToken = StripSpaces(ExtractToken(line, " "));
  m_MainValue = StripSpaces(ExtractValue(line, " "));
}

std::string nptool::InputBlock::ExtractToken(std::string line, std::string separator) {
  // Find the separator
  if (separator == "")
    separator = nptool::token_separator;
  std::size_t pos = line.find(separator.c_str());
  return line.substr(0, pos);
}

std::string nptool::InputBlock::ExtractValue(std::string line, std::string separator) {
  // Find the separator
  if (separator == "")
    separator = nptool::token_separator;
  std::size_t pos = line.find(separator.c_str());
  if (pos != std::string::npos)
    return line.substr(pos + 1);
  else
    return "";
}

void nptool::InputBlock::AddLine(std::string line) {
  m_Token.push_back(ToLower(StripSpaces(ExtractToken(line))));
  m_Value.push_back(StripSpaces(ExtractValue(line)));
  m_Lines.push_back(StripSpaces(line));
}
void nptool::InputBlock::AddLine(std::string token, std::string value) {
  m_Token.push_back(ToLower(token));
  m_Value.push_back(value);
  m_Lines.push_back(token + ": " + value);
}
void nptool::InputBlock::Dump() {
  std::cout << "//////////// Block ////////////" << std::endl;
  std::cout << " * Main Token: " << m_MainToken << std::endl;
  std::cout << " * Main Value: " << m_MainValue << std::endl;
  std::cout << " * Number of Line: " << GetSize() << std::endl;
  for (unsigned int i = 0; i < GetSize(); i++)
    std::cout << "  - " << i + 1 << " " << m_Token[i] << ": " << m_Value[i] << std::endl;
}
bool nptool::InputBlock::HasTokenList(std::vector<std::string> Token) {
  if (m_Token.size() == 0)
    return false;

  bool res = true;
  for (unsigned int i = 0; i < Token.size(); i++)
    res = res && HasToken(Token[i]);

  return res;
}

bool nptool::InputBlock::HasToken(std::string Token) {
  for (unsigned int i = 0; i < m_Token.size(); i++) {
    if (m_Token[i] == ToLower(Token)) {
      return true;
    }
  }
  return false;
}
std::string nptool::InputBlock::GetValue(std::string Token) {
  for (unsigned int i = 0; i < m_Token.size(); i++) {
    if (m_Token[i] == ToLower(Token))
      return m_Value[i];
  }
  return "";
}
double nptool::InputBlock::GetDouble(std::string Token, std::string default_unit, bool silent) {
  std::stringstream iss(GetValue(Token));
  double val;
  std::string unit;
  iss >> val >> unit;
  if (unit == "") {
    if (default_unit != "void")
      std::cout << "WARNING: Using default units for token " << Token << std::endl;
    val = ApplyUnit(val, default_unit);
  }
  else {
    val = ApplyUnit(val, unit);
  }

  if (!silent)
    printf(" %s (%s): %.4f\n", Token.c_str(), default_unit.c_str(), val / ApplyUnit(1, default_unit));

  return val;
}
int nptool::InputBlock::GetInt(std::string Token, bool silent) {
  std::stringstream iss(GetValue(Token));
  int val;
  iss >> val;

  if (!silent)
    printf(" %s: %d\n", Token.c_str(), val);

  return val;
}
bool nptool::InputBlock::GetBool(std::string Token, bool silent) {
  std::stringstream iss(GetValue(Token));
  bool val;
  std::string buffer;
  iss >> buffer;
  ToLower(buffer);
  if (buffer == "true" || buffer == "1")
    val = true;

  if (buffer == "false" || buffer == "0")
    val = false;

  if (!silent) {
    if (val)
      printf(" %s: %s\n", Token.c_str(), "true");
    else
      printf(" %s: %s\n", Token.c_str(), "false");
  }
  return val;
}
std::string nptool::InputBlock::GetString(std::string Token, bool silent) {

  if (!silent)
    printf(" %s: %s\n", Token.c_str(), GetValue(Token).c_str());

  return GetValue(Token);
}
std::vector<double> nptool::InputBlock::GetVector3(std::string Token, std::string default_unit, bool silent) {
  std::stringstream iss(GetValue(Token));

  double x, y, z;
  std::string unit;
  iss >> x >> y >> z >> unit;
  if (unit == "") {
    if (default_unit != "void")
      std::cout << "WARNING: Using default units for token " << Token << std::endl;
    x = ApplyUnit(x, default_unit);
    y = ApplyUnit(y, default_unit);
    z = ApplyUnit(z, default_unit);
  }
  else {
    x = ApplyUnit(x, unit);
    y = ApplyUnit(y, unit);
    z = ApplyUnit(z, unit);
  }

  if (!silent)
    printf(" %s (%s): (%.4f;%.4f;%.4f)\n", Token.c_str(), default_unit.c_str(), x / ApplyUnit(1, default_unit),
           y / ApplyUnit(1, default_unit), z / ApplyUnit(1, default_unit));
  std::vector<double> v = {x, y, z};
  return v;
}
std::vector<std::string> nptool::InputBlock::GetVectorString(std::string Token, bool silent) {

  std::stringstream iss(GetValue(Token));

  std::vector<std::string> val;
  std::string buffer;
  while (iss >> buffer)
    val.push_back(buffer);

  if (!silent) {
    printf(" %s: ", Token.c_str());
    for (unsigned int i = 0; i < val.size(); i++)
      printf("%s ", val[i].c_str());

    printf("\n");
  }
  return val;
}

std::vector<double> nptool::InputBlock::GetVectorDouble(std::string Token, std::string default_unit, bool silent) {

  std::stringstream iss(GetValue(Token));

  std::vector<double> val;
  double buffer;
  while (iss >> buffer)
    val.push_back(buffer);

  // Try to read the unit
  iss.clear();
  std::string unit;
  iss >> unit;

  if (unit == "") {
    if (default_unit != "void")
      std::cout << "WARNING: Using default units for token " << Token << std::endl;
    for (unsigned int i = 0; i < val.size(); i++)
      val[i] = ApplyUnit(val[i], default_unit);
  }
  else {
    for (unsigned int i = 0; i < val.size(); i++)
      val[i] = ApplyUnit(val[i], unit);
  }

  if (!silent) {
    printf(" %s (%s): ", Token.c_str(), default_unit.c_str());
    for (unsigned int i = 0; i < val.size(); i++)
      printf("%f ", val[i] / ApplyUnit(1, default_unit));
    printf("\n");
  }
  return val;
}

std::vector<int> nptool::InputBlock::GetVectorInt(std::string Token, bool silent) {
  std::stringstream iss(GetValue(Token));
  std::vector<int> val;
  int buffer;
  while (iss >> buffer)
    val.push_back(buffer);

  if (!silent) {
    printf(" %s: ", Token.c_str());
    for (unsigned int i = 0; i < val.size(); i++)
      printf(" %d: ", val[i]);
    std::cout << std::endl;
  }
  return val;
}

void nptool::InputParser::Dump() {
  for (unsigned int i = 0; i < m_Block.size(); i++)
    m_Block[i]->Dump();
}
bool nptool::InputParser::IsNotComment(std::string line) {
  line = StripSpaces(line);
  if (line.length() == 0)
    return false;

  std::size_t pos = line.find("%");
  if (pos == std::string::npos)
    return true;
  else
    return false;
}

std::vector<nptool::BlockPtr> nptool::InputParser::GetAllBlocksWithToken(std::string Token) {
  std::vector<nptool::BlockPtr> res;
  for (unsigned int i = 0; i < m_Block.size(); i++) {
    if (m_Block[i]->GetMainToken() == Token) {
      res.push_back(m_Block[i]);
    }
  }

  return res;
}
std::vector<nptool::BlockPtr> nptool::InputParser::GetAllBlocksWithTokenAndValue(std::string Token, std::string Value) {
  std::vector<nptool::BlockPtr> res;
  for (unsigned int i = 0; i < m_Block.size(); i++) {
    if (m_Block[i]->GetMainToken() == Token) {
      if (m_Block[i]->GetMainValue() == Value)
        res.push_back(m_Block[i]);
    }
  }

  return res;
}

std::vector<std::string> nptool::InputParser::GetAllBlocksToken() {
  std::vector<std::string> token;
  for (unsigned int i = 0; i < m_Block.size(); i++) {
    token.push_back(m_Block[i]->GetMainToken());
  }

  return token;
}
std::vector<std::string> nptool::InputParser::GetAllBlocksValues(std::string token) {
  std::vector<std::string> value;
  std::vector<nptool::BlockPtr> blocks = GetAllBlocksWithToken(token);
  unsigned int size = blocks.size();
  for (unsigned int i = 0; i < size; i++) {
    value.push_back(blocks[i]->GetMainValue());
  }

  return value;
}
void nptool::InputParser::SuppressAllBlocksWithToken(std::string Token) {
  for (auto it = m_Block.begin(); it != m_Block.end();) {
    if ((*it)->GetMainToken() == Token) {
      it = m_Block.erase(it);
    }
    else {
      it++;
    }
  }
}
void nptool::InputParser::TreatAliases() {
  // Call the alias block
  auto alias = GetAllBlocksWithToken("alias");
  // List of token:
  std::vector<std::string> token = {"name", "action", "value"};
  // - Action
  //    -> Split : create new block for each value
  //    -> Inplace : Replace the value in existing alias
  // - Value -> The list of value to be used
  for (unsigned int i = 0; i < alias.size(); i++) {
    if (!alias[i]->HasTokenList(token)) {
      // nptool::SendErrorAndExit("nptool::InputParser", "Alias block syntax incorrect");
      exit(1);
    }

    std::cout << "////  Using Alias : " << std::endl;
    std::string name = "@";
    name += alias[i]->GetString("name");
    std::string action = alias[i]->GetString("action");
    std::vector<std::string> value = alias[i]->GetVectorString("value");
    if (action == "replace" && value.size() != 1)
      exit(1);
    // nptool::SendErrorAndExit("nptool::InputParser", "Inplace alias can only take one value");

    // Scan all blocks for aliases
    for (unsigned int b = 0; b < m_Block.size(); b++) {
      unsigned int size = m_Block[b]->GetSize();
      size_t pos;
      // In place case loop over each value and replace them
      if (action == "replace") {
        for (unsigned int v = 0; v < size; v++) {
          while ((pos = m_Block[b]->GetValue(v).find(name)) != std::string::npos) {
            std::string val = m_Block[b]->GetValue(v);
            val.replace(pos, name.length(), value[0]);
            m_Block[b]->SetValue(v, val);
          }
        }
      }

      else if (action == "copy") {
        bool check = false;
        // first pass identify if the block use an alias
        for (unsigned int v = 0; v < size; v++) {
          if (m_Block[b]->GetValue(v).find(name) != std::string::npos)
            check = true;
        }
        if (check) {
          auto originalBlock = m_Block[b]->Copy();
          for (unsigned int a = 0; a < value.size(); a++) {
            auto newBlock = originalBlock->Copy();
            for (unsigned int v = 0; v < size; v++) {
              while ((pos = newBlock->GetValue(v).find(name)) != std::string::npos) {
                std::string val = newBlock->GetValue(v);
                val.replace(pos, name.length(), value[a]);
                newBlock->SetValue(v, val);
              }
            }
            if (a == 0) {
              m_Block[b] = newBlock;
            }
            else {
              auto it = m_Block.begin();
              m_Block.insert(it + b + a, newBlock);
            }
          }
        }
      }
    }
  }
  SuppressAllBlocksWithToken("alias");
}

nptool::BlockPtr nptool::InputParser::ProcessBlock(YAML::const_iterator it) {
  BlockPtr block = std::make_shared<nptool::InputBlock>(it->first.as<std::string>());

  for (YAML::const_iterator itt = it->second.begin(); itt != it->second.end(); ++itt) {
    if (itt->second.size() == 0) {
      block->AddLine(itt->first.as<std::string>(), itt->second.as<std::string>());
    }

    else {
      auto sub_block = ProcessBlock(itt);
      block->AddSubBlock(sub_block);
    }
  }

  return block;
}
void nptool::InputParser::ReadFile(std::string filename, bool silent) {

  // Clear from previous blocks
  Clear();

  try {
    YAML::Node config = YAML::LoadFile(filename);
    if (!silent)
      message("green", "core", "nptool::InputParser", "Reading file " + filename);
    // loop through the block and display them
    std::vector<std::string> line;
    for (YAML::const_iterator it = config.begin(); it != config.end(); ++it) {
      auto block = ProcessBlock(it);
      m_Block.push_back(block);
    }
    TreatAliases();
  }
  catch (YAML::BadFile& badfile) {
    throw(nptool::Error("InputParser", "File " + filename + " does not exist"));
  }
  catch (YAML::ParserException& badfile) {
    throw(nptool::Error("InputParser", "File " + filename + " is not a valid yaml file"));
  }
  catch (...) {
    throw;
  }
}
void nptool::InputParser::Clear() {
  m_Block.clear();
  m_Aliases.clear();
}

double nptool::ApplyUnit(double value, std::string unit) {
  if (unit == "void") // apply no unit
    return value;

  else if (unit == "g/cm3") {
    return value * nptool::g / nptool::cm3;
  }

  else if (unit == "kg/cm3") {
    return value * nptool::kg / nptool::cm3;
  }

  else if (unit == "millimeter") {
    return value * nptool::millimeter;
  }

  else if (unit == "millimeter2") {
    return value * nptool::millimeter2;
  }

  else if (unit == "millimeter3") {
    return value * nptool::millimeter3;
  }

  else if (unit == "centimeter") {
    return value * nptool::centimeter;
  }

  else if (unit == "centimeter2") {
    return value * nptool::centimeter2;
  }

  else if (unit == "centimeter3") {
    return value * nptool::centimeter3;
  }

  else if (unit == "meter") {
    return value * nptool::meter;
  }

  else if (unit == "meter2") {
    return value * nptool::meter2;
  }

  else if (unit == "meter3") {
    return value * nptool::meter3;
  }

  else if (unit == "kilometer") {
    return value * nptool::kilometer;
  }

  else if (unit == "kilometer2") {
    return value * nptool::kilometer2;
  }

  else if (unit == "kilometer3") {
    return value * nptool::kilometer3;
  }

  else if (unit == "parsec") {
    return value * nptool::parsec;
  }

  else if (unit == "micrometer") {
    return value * nptool::micrometer;
  }

  else if (unit == "nanometer") {
    return value * nptool::nanometer;
  }

  else if (unit == "angstrom") {
    return value * nptool::angstrom;
  }

  else if (unit == "fermi") {
    return value * nptool::fermi;
  }

  else if (unit == "barn") {
    return value * nptool::barn;
  }

  else if (unit == "millibarn") {
    return value * nptool::millibarn;
  }

  else if (unit == "microbarn") {
    return value * nptool::microbarn;
  }

  else if (unit == "nanobarn") {
    return value * nptool::nanobarn;
  }

  else if (unit == "picobarn") {
    return value * nptool::picobarn;
  }

  else if (unit == "mm") {
    return value * nptool::mm;
  }

  else if (unit == "um") {
    return value * nptool::um;
  }

  else if (unit == "nm") {
    return value * nptool::nm;
  }

  else if (unit == "mm2") {
    return value * nptool::mm2;
  }

  else if (unit == "mm3") {
    return value * nptool::mm3;
  }

  else if (unit == "cm") {
    return value * nptool::cm;
  }

  else if (unit == "cm2") {
    return value * nptool::cm2;
  }

  else if (unit == "cm3") {
    return value * nptool::cm3;
  }

  else if (unit == "m") {
    return value * nptool::m;
  }

  else if (unit == "m2") {
    return value * nptool::m2;
  }

  else if (unit == "m3") {
    return value * nptool::m3;
  }

  else if (unit == "km") {
    return value * nptool::km;
  }

  else if (unit == "km2") {
    return value * nptool::km2;
  }

  else if (unit == "km3") {
    return value * nptool::km3;
  }

  else if (unit == "pc") {
    return value * nptool::pc;
  }

  else if (unit == "radian") {
    return value * nptool::radian;
  }

  else if (unit == "milliradian") {
    return value * nptool::milliradian;
  }

  else if (unit == "degree") {
    return value * nptool::degree;
  }

  else if (unit == "steradian") {
    return value * nptool::steradian;
  }

  else if (unit == "rad") {
    return value * nptool::rad;
  }

  else if (unit == "mrad") {
    return value * nptool::mrad;
  }

  else if (unit == "sr") {
    return value * nptool::sr;
  }

  else if (unit == "deg") {
    return value * nptool::deg;
  }

  else if (unit == "nanosecond") {
    return value * nptool::nanosecond;
  }

  else if (unit == "second") {
    return value * nptool::second;
  }

  else if (unit == "millisecond") {
    return value * nptool::millisecond;
  }

  else if (unit == "microsecond") {
    return value * nptool::microsecond;
  }

  else if (unit == "picosecond") {
    return value * nptool::picosecond;
  }

  else if (unit == "hertz") {
    return value * nptool::hertz;
  }

  else if (unit == "kilohertz") {
    return value * nptool::kilohertz;
  }

  else if (unit == "megahertz") {
    return value * nptool::megahertz;
  }

  else if (unit == "ns") {
    return value * nptool::ns;
  }

  else if (unit == "us") {
    return value * nptool::us;
  }

  else if (unit == "ms") {
    return value * nptool::ms;
  }

  else if (unit == "eplus") {
    return value * nptool::eplus;
  }

  else if (unit == "e_SI") {
    return value * nptool::e_SI;
  }

  else if (unit == "coulomb") {
    return value * nptool::coulomb;
  }

  else if (unit == "megaelectron") {
    return value * nptool::megaelectronvolt;
  }

  else if (unit == "electronvolt") {
    return value * nptool::electronvolt;
  }

  else if (unit == "kiloelectron") {
    return value * nptool::kiloelectronvolt;
  }

  else if (unit == "gigaelectron") {
    return value * nptool::gigaelectronvolt;
  }

  else if (unit == "teraelectron") {
    return value * nptool::teraelectronvolt;
  }

  else if (unit == "petaelectron") {
    return value * nptool::petaelectronvolt;
  }

  else if (unit == "joule") {
    return value * nptool::joule;
  }

  else if (unit == "MeV") {
    return value * nptool::MeV;
  }

  else if (unit == "eV") {
    return value * nptool::eV;
  }

  else if (unit == "keV") {
    return value * nptool::keV;
  }

  else if (unit == "GeV") {
    return value * nptool::GeV;
  }

  else if (unit == "TeV") {
    return value * nptool::TeV;
  }

  else if (unit == "PeV") {
    return value * nptool::PeV;
  }

  else if (unit == "kilogram") {
    return value * nptool::kilogram;
  }

  else if (unit == "gram") {
    return value * nptool::gram;
  }

  else if (unit == "milligram") {
    return value * nptool::milligram;
  }

  else if (unit == "kg") {
    return value * nptool::kg;
  }

  else if (unit == "g") {
    return value * nptool::g;
  }

  else if (unit == "mg") {
    return value * nptool::mg;
  }

  else if (unit == "watt") {
    return value * nptool::watt;
  }

  else if (unit == "newton") {
    return value * nptool::newton;
  }

  else if (unit == "hep_pascal") {
    return value * nptool::hep_pascal;
  }

  else if (unit == "bar") {
    return value * nptool::bar;
  }

  else if (unit == "atmosphere") {
    return value * nptool::atmosphere;
  }

  else if (unit == "ampere") {
    return value * nptool::ampere;
  }

  else if (unit == "milliampere") {
    return value * nptool::milliampere;
  }

  else if (unit == "microampere") {
    return value * nptool::microampere;
  }

  else if (unit == "nanoampere") {
    return value * nptool::nanoampere;
  }

  else if (unit == "megavolt") {
    return value * nptool::megavolt;
  }

  else if (unit == "kilovolt") {
    return value * nptool::kilovolt;
  }

  else if (unit == "volt") {
    return value * nptool::volt;
  }

  else if (unit == "ohm") {
    return value * nptool::ohm;
  }

  else if (unit == "farad") {
    return value * nptool::farad;
  }

  else if (unit == "millifarad") {
    return value * nptool::millifarad;
  }

  else if (unit == "microfarad") {
    return value * nptool::microfarad;
  }

  else if (unit == "nanofarad") {
    return value * nptool::nanofarad;
  }

  else if (unit == "picofarad") {
    return value * nptool::picofarad;
  }

  else if (unit == "weber") {
    return value * nptool::weber;
  }

  else if (unit == "tesla" || unit == "T") {
    return value * nptool::tesla;
  }

  else if (unit == "gauss") {
    return value * nptool::gauss;
  }

  else if (unit == "kilogauss") {
    return value * nptool::kilogauss;
  }

  else if (unit == "henry") {
    return value * nptool::henry;
  }

  else if (unit == "kelvin") {
    return value * nptool::kelvin;
  }

  else if (unit == "mole") {
    return value * nptool::mole;
  }

  else if (unit == "becquerel") {
    return value * nptool::becquerel;
  }

  else if (unit == "curie") {
    return value * nptool::curie;
  }

  else if (unit == "gray") {
    return value * nptool::gray;
  }

  else if (unit == "kilogray") {
    return value * nptool::kilogray;
  }

  else if (unit == "milligray") {
    return value * nptool::milligray;
  }

  else if (unit == "microgray") {
    return value * nptool::microgray;
  }

  else if (unit == "candela") {
    return value * nptool::candela;
  }

  else if (unit == "lumen") {
    return value * nptool::lumen;
  }

  else if (unit == "lux") {
    return value * nptool::lux;
  }

  else if (unit == "perCent") {
    return value * nptool::perCent;
  }

  else if (unit == "perThousand") {
    return value * nptool::perThousand;
  }

  else if (unit == "perMillion") {
    return value * nptool::perMillion;
  }

  else {
    std::cout << "WARNING: Unknown unit " << unit << std::endl;
    return value;
  }
}