// This is the file "FactorizedJetCorrectorCalculator.cc".
// This is the implementation of the class FactorizedJetCorrectorCalculator.
// Author: Konstantinos Kousouris, Philipp Schieferdecker
// Email:  kkousour@fnal.gov, philipp.schieferdecker@cern.ch

#include "CondFormats/JetMETObjects/interface/FactorizedJetCorrectorCalculator.h"
#include "CondFormats/JetMETObjects/interface/SimpleJetCorrector.h"
#include "CondFormats/JetMETObjects/interface/JetCorrectorParameters.h"
#include "CondFormats/JetMETObjects/interface/Utilities.h"
#include "Math/PtEtaPhiE4D.h"
#include "Math/Vector3D.h"
#include "Math/LorentzVector.h"
#include <vector>
#include <string>
#include <sstream>

//------------------------------------------------------------------------
//--- Default FactorizedJetCorrectorCalculator constructor -------------------------
//------------------------------------------------------------------------
FactorizedJetCorrectorCalculator::FactorizedJetCorrectorCalculator() {}
//------------------------------------------------------------------------
//--- FactorizedJetCorrectorCalculator constructor ---------------------------------
//------------------------------------------------------------------------
FactorizedJetCorrectorCalculator::FactorizedJetCorrectorCalculator(const std::string& fLevels,
                                                                   const std::string& fFiles,
                                                                   const std::string& fOptions) {
  initCorrectors(fLevels, fFiles, fOptions);
}
//------------------------------------------------------------------------
//--- FactorizedJetCorrectorCalculator constructor ---------------------------------
//------------------------------------------------------------------------
FactorizedJetCorrectorCalculator::FactorizedJetCorrectorCalculator(
    const std::vector<JetCorrectorParameters>& fParameters) {
  for (unsigned i = 0; i < fParameters.size(); i++) {
    std::string ss = fParameters[i].definitions().level();
    if (ss == "L1Offset")
      mLevels.push_back(kL1);
    else if (ss == "L1JPTOffset")
      mLevels.push_back(kL1JPT);
    else if (ss == "L2Relative")
      mLevels.push_back(kL2);
    else if (ss == "L3Absolute")
      mLevels.push_back(kL3);
    else if (ss == "L2L3Residual")
      mLevels.push_back(kL2L3Res);
    else if (ss == "L4EMF")
      mLevels.push_back(kL4);
    else if (ss == "L5Flavor")
      mLevels.push_back(kL5);
    else if (ss == "L6SLB")
      mLevels.push_back(kL6);
    else if (ss == "L7Parton")
      mLevels.push_back(kL7);
    else if (ss == "L1FastJet")
      mLevels.push_back(kL1fj);
    else {
      std::stringstream sserr;
      sserr << "unknown correction level " << ss;
      handleError("FactorizedJetCorrectorCalculator", sserr.str());
    }
    mCorrectors.push_back(new SimpleJetCorrector(fParameters[i]));
    mBinTypes.push_back(mapping(mCorrectors[i]->parameters().definitions().binVar()));
    mParTypes.push_back(mapping(mCorrectors[i]->parameters().definitions().parVar()));
  }
}

//------------------------------------------------------------------------
//--- FactorizedJetCorrectorCalculator destructor ----------------------------------
//------------------------------------------------------------------------
FactorizedJetCorrectorCalculator::~FactorizedJetCorrectorCalculator() {
  for (unsigned i = 0; i < mCorrectors.size(); i++)
    delete mCorrectors[i];
}
//------------------------------------------------------------------------
//--- initialises the correctors -----------------------------------------
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::initCorrectors(const std::string& fLevels,
                                                      const std::string& fFiles,
                                                      const std::string& fOptions) {
  //---- Read the CorrectionLevels string and parse the requested sub-correction levels.
  std::vector<std::string> tmp = parseLevels(removeSpaces(fLevels));
  for (unsigned i = 0; i < tmp.size(); i++) {
    if (tmp[i] == "L1Offset")
      mLevels.push_back(kL1);
    else if (tmp[i] == "L1JPTOffset")
      mLevels.push_back(kL1JPT);
    else if (tmp[i] == "L2Relative")
      mLevels.push_back(kL2);
    else if (tmp[i] == "L3Absolute")
      mLevels.push_back(kL3);
    else if (tmp[i] == "L2L3Residual")
      mLevels.push_back(kL2L3Res);
    else if (tmp[i] == "L4EMF")
      mLevels.push_back(kL4);
    else if (tmp[i] == "L5Flavor")
      mLevels.push_back(kL5);
    else if (tmp[i] == "L6SLB")
      mLevels.push_back(kL6);
    else if (tmp[i] == "L7Parton")
      mLevels.push_back(kL7);
    else if (tmp[i] == "L1FastJet")
      mLevels.push_back(kL1fj);
    else {
      std::stringstream sserr;
      sserr << "unknown correction level " << tmp[i];
      handleError("FactorizedJetCorrectorCalculator", sserr.str());
    }
  }
  //---- Read the parameter filenames string and parse the requested sub-correction tags.
  std::vector<std::string> Files = parseLevels(removeSpaces(fFiles));
  //---- Read the Options string and define the FlavorOption and PartonOption.
  std::string FlavorOption = parseOption(removeSpaces(fOptions), "L5Flavor");
  std::string PartonOption = parseOption(removeSpaces(fOptions), "L7Parton");
  //---- Check the consistency between tags and requested sub-corrections.
  checkConsistency(tmp, Files);
  //---- Create instances of the requested sub-correctors.
  for (unsigned i = 0; i < mLevels.size(); i++) {
    if (mLevels[i] == kL1 || mLevels[i] == kL1JPT || mLevels[i] == kL2 || mLevels[i] == kL3 || mLevels[i] == kL4 ||
        mLevels[i] == kL6 || mLevels[i] == kL1fj)
      mCorrectors.push_back(new SimpleJetCorrector(Files[i]));
    else if (mLevels[i] == kL5 && FlavorOption.length() == 0)
      handleError("FactorizedJetCorrectorCalculator",
                  "must specify flavor option when requesting L5Flavor correction!");
    else if (mLevels[i] == kL5 && FlavorOption.length() > 0)
      mCorrectors.push_back(new SimpleJetCorrector(Files[i], FlavorOption));
    else if (mLevels[i] == kL7 && PartonOption.length() == 0)
      handleError("FactorizedJetCorrectorCalculator",
                  "must specify parton option when requesting L7Parton correction!");
    else if (mLevels[i] == kL7 && PartonOption.length() > 0)
      mCorrectors.push_back(new SimpleJetCorrector(Files[i], PartonOption));
    else {
      std::stringstream sserr;
      sserr << "unknown correction level " << tmp[i];
      handleError("FactorizedJetCorrectorCalculator", sserr.str());
    }
    mBinTypes.push_back(mapping(mCorrectors[i]->parameters().definitions().binVar()));
    mParTypes.push_back(mapping(mCorrectors[i]->parameters().definitions().parVar()));
  }
}
//------------------------------------------------------------------------
//--- Mapping between variable names and variable types ------------------
//------------------------------------------------------------------------
std::vector<FactorizedJetCorrectorCalculator::VarTypes> FactorizedJetCorrectorCalculator::mapping(
    const std::vector<std::string>& fNames) const {
  std::vector<VarTypes> result;
  for (unsigned i = 0; i < fNames.size(); i++) {
    const std::string& ss = fNames[i];
    if (ss == "JetPt")
      result.push_back(kJetPt);
    else if (ss == "JetEta")
      result.push_back(kJetEta);
    else if (ss == "JetPhi")
      result.push_back(kJetPhi);
    else if (ss == "JetE")
      result.push_back(kJetE);
    else if (ss == "JetEMF")
      result.push_back(kJetEMF);
    else if (ss == "RelLepPt")
      result.push_back(kRelLepPt);
    else if (ss == "PtRel")
      result.push_back(kPtRel);
    else if (ss == "NPV")
      result.push_back(kNPV);
    else if (ss == "JetA")
      result.push_back(kJetA);
    else if (ss == "Rho")
      result.push_back(kRho);
    else if (ss == "JPTrawE")
      result.push_back(kJPTrawE);
    else if (ss == "JPTrawEt")
      result.push_back(kJPTrawEt);
    else if (ss == "JPTrawPt")
      result.push_back(kJPTrawPt);
    else if (ss == "JPTrawEta")
      result.push_back(kJPTrawEta);
    else if (ss == "JPTrawOff")
      result.push_back(kJPTrawOff);
    else {
      std::stringstream sserr;
      sserr << "unknown parameter name: " << ss;
      handleError("FactorizedJetCorrectorCalculator", sserr.str());
    }
  }
  return result;
}
//------------------------------------------------------------------------
//--- Consistency checker ------------------------------------------------
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::checkConsistency(const std::vector<std::string>& fLevels,
                                                        const std::vector<std::string>& fTags) {
  //---- First check: the number of tags must be equal to the number of sub-corrections.
  if (fLevels.size() != fTags.size()) {
    std::stringstream sserr;
    sserr << "number of correction levels: " << fLevels.size() << " doesn't match # of tags: " << fTags.size();
    handleError("FactorizedJetCorrectorCalculator", sserr.str());
  }
  //---- Second check: each tag must contain the corresponding sub-correction level.
  for (unsigned int i = 0; i < fTags.size(); i++) {
    if ((int)fTags[i].find(fLevels[i]) < 0) {
      std::stringstream sserr;
      sserr << "inconsistent tag: " << fTags[i] << " for "
            << "the requested correction: " << fLevels[i];
      handleError("FactorizedJetCorrectorCalculator", sserr.str());
    }
  }
}
//------------------------------------------------------------------------
//--- String parser ------------------------------------------------------
//------------------------------------------------------------------------
std::vector<std::string> FactorizedJetCorrectorCalculator::parseLevels(const std::string& ss) const {
  std::vector<std::string> result;
  unsigned int pos(0), j, newPos;
  int i;
  std::string tmp;
  //---- The ss string must be of the form: "LX:LY:...:LZ"
  while (pos < ss.length()) {
    tmp = "";
    i = ss.find(':', pos);
    if (i < 0 && pos == 0) {
      result.push_back(ss);
      pos = ss.length();
    } else if (i < 0 && pos > 0) {
      for (j = pos; j < ss.length(); j++)
        tmp += ss[j];
      result.push_back(tmp);
      pos = ss.length();
    } else {
      newPos = i;
      for (j = pos; j < newPos; j++)
        tmp += ss[j];
      result.push_back(tmp);
      pos = newPos + 1;
    }
  }
  return result;
}
//------------------------------------------------------------------------
//--- String parser ------------------------------------------------------
//------------------------------------------------------------------------
std::string FactorizedJetCorrectorCalculator::parseOption(const std::string& ss, const std::string& type) const {
  std::string result;
  int pos1(-1), pos2(-1);
  //---- The ss string must be of the form: "type1:option1&type2:option2&..."
  pos1 = ss.find(type + ":");
  if (pos1 < 0)
    result = "";
  else {
    pos2 = ss.find('&', pos1 + type.length() + 1);
    if (pos2 < 0)
      result = ss.substr(pos1 + type.length() + 1, ss.length() - pos1 - type.length() - 1);
    else
      result = ss.substr(pos1 + type.length() + 1, pos2 - pos1 - type.length() - 1);
  }
  return result;
}
//------------------------------------------------------------------------
//--- String manipulator -------------------------------------------------
//------------------------------------------------------------------------
std::string FactorizedJetCorrectorCalculator::removeSpaces(const std::string& ss) const {
  std::string result("");
  std::string aChar;
  for (unsigned int i = 0; i < ss.length(); i++) {
    aChar = ss.substr(i, 1);
    if (aChar != " ")
      result += aChar;
  }
  return result;
}
//------------------------------------------------------------------------
//--- Returns the correction ---------------------------------------------
//------------------------------------------------------------------------
float FactorizedJetCorrectorCalculator::getCorrection(FactorizedJetCorrectorCalculator::VariableValues& iValues) const {
  std::vector<float>&& vv = getSubCorrections(iValues);
  return vv.back();
}
//------------------------------------------------------------------------
//--- Returns the vector of subcorrections, up to a given level ----------
//------------------------------------------------------------------------
std::vector<float> FactorizedJetCorrectorCalculator::getSubCorrections(
    FactorizedJetCorrectorCalculator::VariableValues& iValues) const {
  float scale, factor;
  std::vector<float> factors;
  std::vector<float> vx, vy;
  factor = 1;
  for (unsigned int i = 0; i < mLevels.size(); i++) {
    vx = fillVector(mBinTypes[i], iValues);
    vy = fillVector(mParTypes[i], iValues);
    //if (mLevels[i]==kL2 || mLevels[i]==kL6)
    //mCorrectors[i]->setInterpolation(true);
    scale = mCorrectors[i]->correction(vx, vy);
    //----- For JPT jets, the offset is stored in order to be used later by the the L1JPTOffset
    if ((mLevels[i] == kL1 || mLevels[i] == kL1fj) && iValues.mIsJPTrawP4set && !iValues.mIsJPTrawOFFset) {
      iValues.setJPTrawOff(scale);
    } else if (mLevels[i] == kL6 && iValues.mAddLepToJet) {
      scale *= 1.0 + getLepPt(iValues) / iValues.mJetPt;
      iValues.mJetE *= scale;
      iValues.mJetPt *= scale;
      factor *= scale;
    } else {
      iValues.mJetE *= scale;
      iValues.mJetPt *= scale;
      factor *= scale;
    }
    factors.push_back(factor);
  }
  iValues.reset();
  return factors;
}
//------------------------------------------------------------------------
//--- Reads the parameter names and fills a vector of floats -------------
//------------------------------------------------------------------------
std::vector<float> FactorizedJetCorrectorCalculator::fillVector(
    const std::vector<VarTypes>& fVarTypes, const FactorizedJetCorrectorCalculator::VariableValues& iValues) const {
  //  std::vector<VarTypes> fVarTypes = _fVarTypes;
  std::vector<float> result;
  for (unsigned i = 0; i < fVarTypes.size(); i++) {
    if (fVarTypes[i] == kJetEta) {
      if (!iValues.mIsJetEtaset)
        handleError("FactorizedJetCorrectorCalculator", "jet eta is not set");
      result.push_back(iValues.mJetEta);
    } else if (fVarTypes[i] == kNPV) {
      if (!iValues.mIsNPVset)
        handleError("FactorizedJetCorrectorCalculator", "number of primary vertices is not set");
      result.push_back(iValues.mNPV);
    } else if (fVarTypes[i] == kJetPt) {
      if (!iValues.mIsJetPtset)
        handleError("FactorizedJetCorrectorCalculator", "jet pt is not set");
      result.push_back(iValues.mJetPt);
    } else if (fVarTypes[i] == kJetPhi) {
      if (!iValues.mIsJetPhiset)
        handleError("FactorizedJetCorrectorCalculator", "jet phi is not set");
      result.push_back(iValues.mJetPhi);
    } else if (fVarTypes[i] == kJetE) {
      if (!iValues.mIsJetEset)
        handleError("FactorizedJetCorrectorCalculator", "jet E is not set");
      result.push_back(iValues.mJetE);
    } else if (fVarTypes[i] == kJetEMF) {
      if (!iValues.mIsJetEMFset)
        handleError("FactorizedJetCorrectorCalculator", "jet EMF is not set");
      result.push_back(iValues.mJetEMF);
    } else if (fVarTypes[i] == kJetA) {
      if (!iValues.mIsJetAset)
        handleError("FactorizedJetCorrectorCalculator", "jet area is not set");
      result.push_back(iValues.mJetA);
    } else if (fVarTypes[i] == kRho) {
      if (!iValues.mIsRhoset)
        handleError("FactorizedJetCorrectorCalculator", "fastjet density Rho is not set");
      result.push_back(iValues.mRho);
    } else if (fVarTypes[i] == kJPTrawE) {
      if (!iValues.mIsJPTrawP4set)
        handleError("FactorizedJetCorrectorCalculator", "raw CaloJet P4 for JPT is not set");
      result.push_back(iValues.mJPTrawE);
    } else if (fVarTypes[i] == kJPTrawEt) {
      if (!iValues.mIsJPTrawP4set)
        handleError("FactorizedJetCorrectorCalculator", "raw CaloJet P4 for JPT is not set");
      result.push_back(iValues.mJPTrawEt);
    } else if (fVarTypes[i] == kJPTrawPt) {
      if (!iValues.mIsJPTrawP4set)
        handleError("FactorizedJetCorrectorCalculator", "raw CaloJet P4 for JPT is not set");
      result.push_back(iValues.mJPTrawPt);
    } else if (fVarTypes[i] == kJPTrawEta) {
      if (!iValues.mIsJPTrawP4set)
        handleError("FactorizedJetCorrectorCalculator", "raw CaloJet P4 for JPT is not set");
      result.push_back(iValues.mJPTrawEta);
    } else if (fVarTypes[i] == kJPTrawOff) {
      if (!iValues.mIsJPTrawOFFset)
        handleError("FactorizedJetCorrectorCalculator", "Offset correction for JPT is not set");
      result.push_back(iValues.mJPTrawOff);
    } else if (fVarTypes[i] == kRelLepPt) {
      if (!iValues.mIsJetPtset || !iValues.mIsAddLepToJetset || !iValues.mIsLepPxset || !iValues.mIsLepPyset)
        handleError("FactorizedJetCorrectorCalculator", "can't calculate rel lepton pt");
      result.push_back(getRelLepPt(iValues));
    } else if (fVarTypes[i] == kPtRel) {
      if (!iValues.mIsJetPtset || !iValues.mIsJetEtaset || !iValues.mIsJetPhiset || !iValues.mIsJetEset ||
          !iValues.mIsAddLepToJetset || !iValues.mIsLepPxset || !iValues.mIsLepPyset || !iValues.mIsLepPzset)
        handleError("FactorizedJetCorrectorCalculator", "can't calculate ptrel");
      result.push_back(getPtRel(iValues));
    } else {
      std::stringstream sserr;
      sserr << "unknown parameter " << fVarTypes[i];
      handleError("FactorizedJetCorrectorCalculator", sserr.str());
    }
  }
  return result;
}
//------------------------------------------------------------------------
//--- Calculate the lepPt (needed for the SLB) ---------------------------
//------------------------------------------------------------------------
float FactorizedJetCorrectorCalculator::getLepPt(const FactorizedJetCorrectorCalculator::VariableValues& iValues) const {
  return std::sqrt(iValues.mLepPx * iValues.mLepPx + iValues.mLepPy * iValues.mLepPy);
}
//------------------------------------------------------------------------
//--- Calculate the relLepPt (needed for the SLB) ---------------------------
//------------------------------------------------------------------------
float FactorizedJetCorrectorCalculator::getRelLepPt(
    const FactorizedJetCorrectorCalculator::VariableValues& iValues) const {
  float lepPt = getLepPt(iValues);
  return (iValues.mAddLepToJet) ? lepPt / (iValues.mJetPt + lepPt) : lepPt / iValues.mJetPt;
}
//------------------------------------------------------------------------
//--- Calculate the PtRel (needed for the SLB) ---------------------------
//------------------------------------------------------------------------
float FactorizedJetCorrectorCalculator::getPtRel(const FactorizedJetCorrectorCalculator::VariableValues& iValues) const {
  typedef ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiE4D<float> > PtEtaPhiELorentzVector;
  typedef ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<float> > XYZVector;
  PtEtaPhiELorentzVector jet;
  XYZVector lep;
  jet.SetPt(iValues.mJetPt);
  jet.SetEta(iValues.mJetEta);
  jet.SetPhi(iValues.mJetPhi);
  jet.SetE(iValues.mJetE);
  lep.SetXYZ(iValues.mLepPx, iValues.mLepPy, iValues.mLepPz);
  float lj_x = (iValues.mAddLepToJet) ? lep.X() + jet.Px() : jet.Px();
  float lj_y = (iValues.mAddLepToJet) ? lep.Y() + jet.Py() : jet.Py();
  float lj_z = (iValues.mAddLepToJet) ? lep.Z() + jet.Pz() : jet.Pz();
  // absolute values squared
  float lj2 = lj_x * lj_x + lj_y * lj_y + lj_z * lj_z;
  if (lj2 <= 0) {
    std::stringstream sserr;
    sserr << "lepton+jet momentum sq is not positive: " << lj2;
    handleError("FactorizedJetCorrectorCalculator", sserr.str());
  }
  float lep2 = lep.X() * lep.X() + lep.Y() * lep.Y() + lep.Z() * lep.Z();
  // projection vec(mu) to lepjet axis
  float lepXlj = lep.X() * lj_x + lep.Y() * lj_y + lep.Z() * lj_z;
  // absolute value squared and normalized
  float pLrel2 = lepXlj * lepXlj / lj2;
  // lep2 = pTrel2 + pLrel2
  float pTrel2 = lep2 - pLrel2;
  return (pTrel2 > 0) ? std::sqrt(pTrel2) : 0.0;
}

//------------------------------------------------------------------------
//--- Default FactorizedJetCorrectorCalculator::VariableValues constructor -------------------------
//------------------------------------------------------------------------
FactorizedJetCorrectorCalculator::VariableValues::VariableValues() {
  mJetEta = -9999;
  mJetPt = -9999;
  mJetPhi = -9999;
  mJetE = -9999;
  mJetEMF = -9999;
  mJetA = -9999;
  mRho = -9999;
  mLepPx = -9999;
  mLepPy = -9999;
  mLepPz = -9999;
  mNPV = -9999;
  mJPTrawE = -9999;
  mJPTrawEt = -9999;
  mJPTrawPt = -9999;
  mJPTrawEta = -9999;
  mJPTrawOff = -9999;
  mAddLepToJet = false;
  mIsNPVset = false;
  mIsJetEset = false;
  mIsJetPtset = false;
  mIsJetPhiset = false;
  mIsJetEtaset = false;
  mIsJetEMFset = false;
  mIsJetAset = false;
  mIsRhoset = false;
  mIsJPTrawP4set = false;
  mIsJPTrawOFFset = false;
  mIsLepPxset = false;
  mIsLepPyset = false;
  mIsLepPzset = false;
  mIsAddLepToJetset = false;
}

//------------------------------------------------------------------------
//--- Setters ------------------------------------------------------------
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setNPV(int fNPV) {
  mNPV = fNPV;
  mIsNPVset = true;
}
void FactorizedJetCorrectorCalculator::VariableValues::setJetEta(float fEta) {
  mJetEta = fEta;
  mIsJetEtaset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setJetPt(float fPt) {
  mJetPt = fPt;
  mIsJetPtset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setJetPhi(float fPhi) {
  mJetPhi = fPhi;
  mIsJetPhiset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setJetE(float fE) {
  mJetE = fE;
  mIsJetEset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setJetEMF(float fEMF) {
  mJetEMF = fEMF;
  mIsJetEMFset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setJetA(float fA) {
  mJetA = fA;
  mIsJetAset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setRho(float fRho) {
  mRho = fRho;
  mIsRhoset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setJPTrawP4(const TLorentzVector& fJPTrawP4) {
  mJPTrawE = fJPTrawP4.Energy();
  mJPTrawEt = fJPTrawP4.Et();
  mJPTrawPt = fJPTrawP4.Pt();
  mJPTrawEta = fJPTrawP4.Eta();
  mIsJPTrawP4set = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setJPTrawOff(float fJPTrawOff) {
  mJPTrawOff = fJPTrawOff;
  mIsJPTrawOFFset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setLepPx(float fPx) {
  mLepPx = fPx;
  mIsLepPxset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setLepPy(float fPy) {
  mLepPy = fPy;
  mIsLepPyset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setLepPz(float fPz) {
  mLepPz = fPz;
  mIsLepPzset = true;
}
//------------------------------------------------------------------------
void FactorizedJetCorrectorCalculator::VariableValues::setAddLepToJet(bool fAddLepToJet) {
  mAddLepToJet = fAddLepToJet;
  mIsAddLepToJetset = true;
}

void FactorizedJetCorrectorCalculator::VariableValues::reset() {
  mIsNPVset = false;
  mIsJetEset = false;
  mIsJetPtset = false;
  mIsJetPhiset = false;
  mIsJetEtaset = false;
  mIsJetEMFset = false;
  mIsJetAset = false;
  mIsRhoset = false;
  mIsJPTrawP4set = false;
  mIsJPTrawOFFset = false;
  mIsLepPxset = false;
  mIsLepPyset = false;
  mIsLepPzset = false;
  mAddLepToJet = false;
}
