Asymmetry estimateAsymmetry(
    const TH1* hist, const TH2* cov, 
    const char * minName = "Minuit2",
    const char *algoName = "" )
{
    
    TH1* normHist=(TH1*)hist->Clone("normHist");
    TH2* normCov=(TH2*)cov->Clone("normCov");
    
    
    
    normHist->Scale(1.0/hist->Integral());
    normCov->Scale(1.0/hist->Integral()/hist->Integral());

    const int N = hist->GetNbinsX();

    TMatrixD covMatrix(N,N);
    
    for (int i=0; i<N;++i)
    {
        for (int j=0; j<N;++j)
        {
            covMatrix[i][j]=normCov->GetBinContent(i+1,j+1);
        }
    }
    TMatrixD invCovMatrix = TMatrixD(TMatrixD::kInverted,covMatrix);
    
    
    
    ROOT::Math::Minimizer* min = ROOT::Math::Factory::CreateMinimizer(minName, algoName);

    // set tolerance , etc...
    min->SetMaxFunctionCalls(1000000); // for Minuit/Minuit2 
    min->SetMaxIterations(10000);  // for GSL 
    min->SetTolerance(0.001);
    min->SetPrintLevel(1);
    //const double xx[1] = {0.5};
    std::function<double(const TH1*, const TMatrixD*, const double*)> unboundFct = chi2A;
    std::function<double(const double*)> boundFct = std::bind(unboundFct,normHist, &invCovMatrix, std::placeholders::_1);
    
    //boundFct(xx);
    ROOT::Math::Functor fct(boundFct,1); 


    min->SetFunction(fct);

    min->SetVariable(0,"A",0.2, 0.01);
    min->Minimize(); 

    const double *xs = min->X();
    const double *error = min->Errors();
    log(INFO,"min: %f\n",xs[0]);
    log(INFO,"err: %f\n",error[0]);
    Asymmetry res;
    res.mean=xs[0];
    res.uncertainty=error[0];
    return res;
}
int main(int argc, char** argv)
{
//    ROOT::Math::Minimizer* minuit = ROOT::Math::Factory::CreateMinimizer("Genetic");  //---> next ROOT  release!
 ROOT::Math::Minimizer* minuit = ROOT::Math::Factory::CreateMinimizer("Minuit", "Migrad2");
 ROOT::Math::Functor functorChi2(&Chi2Func,6); 
 
 TString genCut; //==== (eleFBrem<0.8&&eleCharge>0)

 bool traslationX ;
 bool traslationY ;
 bool traslationZ ;
 bool rotationPhi ;
 bool rotationTheta ;
 bool rotationPsi ;
 
 std::string fileName (argv[1]) ;
 boost::shared_ptr<edm::ParameterSet> parameterSet = edm::readConfig(fileName) ;

 edm::ParameterSet subPSetInput = parameterSet->getParameter<edm::ParameterSet> ("inputTree") ;
 std::vector<std::string> nameFileIn = subPSetInput.getParameter<std::vector<std::string> > ("inputFiles") ;
 std::string nameTree = subPSetInput.getParameter<std::string> ("nameTree") ;
 std::string selection = subPSetInput.getParameter<std::string> ("selection") ;
 genCut = Form("%s",selection.c_str());
 traslationX = subPSetInput.getParameter<bool> ("traslationX") ;
 traslationY = subPSetInput.getParameter<bool> ("traslationY") ;
 traslationZ = subPSetInput.getParameter<bool> ("traslationZ") ;
 rotationPhi   = subPSetInput.getParameter<bool> ("rotationPhi") ;
 rotationTheta = subPSetInput.getParameter<bool> ("rotationTheta") ;
 rotationPsi   = subPSetInput.getParameter<bool> ("rotationPsi") ;
     
 double setRotationPhi     = subPSetInput.getUntrackedParameter<double> ("setRotationPhi",0) ;
 double setRotationTheta   = subPSetInput.getUntrackedParameter<double> ("setRotationTheta",0) ;
 double setRotationPsi     = subPSetInput.getUntrackedParameter<double> ("setRotationPsi",0) ;

 
 even = subPSetInput.getUntrackedParameter<bool> ("even",true) ;
 odd = subPSetInput.getUntrackedParameter<bool> ("odd",true) ;

 edm::ParameterSet subPSetOutput = parameterSet->getParameter<edm::ParameterSet> ("outputTree") ;
 std::string nameFileOut = subPSetOutput.getParameter<std::string> ("outputFile") ;

 //==== plot input/output ====
 std::cout << " nameFileIn = ";
 for (unsigned int i=0; i<nameFileIn.size(); i++ ) std::cout << "    " << nameFileIn.at(i) << std::endl;
 std::cout << " nameFileOut = " << nameFileOut << std::endl;
 std::cout << " genCut = " << genCut.Data() << std::endl;
  
 ///==== input DATA ==== 
 myTree = new TChain(nameTree.c_str());
 int numberInput = 0;
 for (std::vector<std::string>::const_iterator listIt = nameFileIn.begin () ; listIt != nameFileIn.end () ; ++listIt) {
  numberInput++;
  myTree->Add (listIt->c_str ()) ;
  if (numberInput%4 == 0) std::cerr << "Input number " << numberInput << " ... " << listIt->c_str () << std::endl;
 }


 ///==== bias functions ==== 
 
 std::string FunctionDetaName = subPSetInput.getUntrackedParameter<std::string> ("DetaBias","0") ; // x = eta, y = charge
 std::string FunctionDphiName = subPSetInput.getUntrackedParameter<std::string> ("DphiBias","0") ;

 FunctionDeta = new TF2 ("DetaBias",FunctionDetaName.c_str(),-5,5,-2,2);
 FunctionDphi = new TF2 ("DphiBias",FunctionDphiName.c_str(),-5,5,-2,2);

 //==== output DATA ====
 
 ///==== Input ECAL position ====
 std::string inputFilesPosition = subPSetInput.getUntrackedParameter<std::string> ("inputFilesPosition","") ;

 ///==== Build variables ====
 
 double DX_SC_Mean[4];
 double DX_SC_RMS[4];
 double DY_SC_Mean[4];
 double DY_SC_RMS[4];
 double DZ_SC_Mean[4];
 double DZ_SC_RMS[4];
 
 double DTHETAe_SC_Mean[4];
 double DTHETAe_SC_RMS[4];
 double DPSIe_SC_Mean[4];
 double DPSIe_SC_RMS[4];
 double DPHIe_SC_Mean[4];
 double DPHIe_SC_RMS[4];
 
 
 std::ifstream* file;
 if (inputFilesPosition != ""){
  file = new std::ifstream(inputFilesPosition.c_str());
  if(!file->is_open())
  {
   return false;
  }
 }
 
 for (int iSC = 0; iSC<4; iSC++){
  TString cut;
  cut = Form("%s && iDetEB < -10 && iDetEE == %d",genCut.Data(),iSC);
  std::cout << "  cut = " << cut.Data() << std::endl;
  
  ///===========================
  ///==== Chi2 minimization ====
  
  double inputDX = 0;
  double inputDY = 0;
  double inputDZ = 0;
  double inputDPHIe = 0;
  double inputDTHETAe = 0;
  double inputDPSIe = 0;
  if (inputFilesPosition != ""){
   std::string buffer;
   getline(*file,buffer);
   std::stringstream line( buffer );
   line >> inputDPHIe;
   line >> inputDTHETAe;
   line >> inputDPSIe;
   line >> inputDX; inputDX/=100;
   line >> inputDY; inputDY/=100;
   line >> inputDZ; inputDZ/=100; 
  }
  
  std::cerr << " inputDPHIe   = " << inputDPHIe << std::endl;
  std::cerr << " inputDTHETAe = " << inputDTHETAe << std::endl;
  std::cerr << " inputDPSIe   = " << inputDPSIe << std::endl;
  std::cerr << " inputDX      = " << inputDX << std::endl;
  std::cerr << " inputDY      = " << inputDY << std::endl;
  std::cerr << " inputDZ      = " << inputDZ << std::endl;

  
  std::cout << " Chi2 minimization " << std::endl;
  
  globalCut = cut;
  //   unsigned int iNoSteps = 1000;
  //   unsigned int iPar_NoBG = 0;
  minuit->SetFunction(functorChi2);
  minuit->SetMaxFunctionCalls(100000);
  minuit->SetMaxIterations(10000);
  minuit->SetTolerance(0.000002);
  
  if (traslationX)  minuit->SetLimitedVariable(0,"DX",inputDX, 0.00001,-0.050,0.050);
  else  minuit->SetFixedVariable(0,"DX",0);

  if (traslationY)  minuit->SetLimitedVariable(1,"DY",inputDY, 0.00001,-0.050,0.050);
  else  minuit->SetFixedVariable(1,"DY",0);

  if (traslationZ)  minuit->SetLimitedVariable(2,"DZ",inputDZ, 0.00001,-0.050,0.050);
  else  minuit->SetFixedVariable(2,"DZ",0);


  if (rotationPhi)  minuit->SetLimitedVariable(3,"DPHIe",inputDPHIe, 0.00001,-3.15,3.15);
  else  minuit->SetFixedVariable(3,"DPHIe",inputDPHIe);

  if (rotationTheta)  minuit->SetLimitedVariable(4,"DTHETAe",inputDTHETAe, 0.00001,-3.15,3.15);
  else  minuit->SetFixedVariable(4,"DTHETAe",inputDTHETAe);

  if (rotationPsi)  minuit->SetLimitedVariable(5,"DPSIe",inputDPSIe, 0.00001,-3.15,3.15);
  else  minuit->SetFixedVariable(5,"DPSIe",inputDPSIe);

 
  minuit->Minimize();
  minuit->PrintResults();
  
  DX_SC_Mean[iSC] = (minuit->X()[0]);
  DY_SC_Mean[iSC] = (minuit->X()[1]);
  DZ_SC_Mean[iSC] = (minuit->X()[2]);
  
  DX_SC_RMS[iSC] = (minuit->Errors()[0]);
  DY_SC_RMS[iSC] = (minuit->Errors()[1]);
  DZ_SC_RMS[iSC] = (minuit->Errors()[2]);
  
  DPHIe_SC_Mean[iSC] = (minuit->X()[3]);
  DTHETAe_SC_Mean[iSC] = (minuit->X()[4]);
  DPSIe_SC_Mean[iSC] = (minuit->X()[5]);
  
  DPHIe_SC_RMS[iSC] = (minuit->Errors()[3]);
  DTHETAe_SC_RMS[iSC] = (minuit->Errors()[4]);
  DPSIe_SC_RMS[iSC] = (minuit->Errors()[5]);
  
  ///==== end Chi2 minimization ====
  
  std::cout << " iSC = " << iSC << " DPhi =   " << DPHIe_SC_Mean[iSC]   << " +/- " << DPHIe_SC_RMS[iSC]   << std::endl;
  std::cout << " iSC = " << iSC << " DTheta = " << DTHETAe_SC_Mean[iSC] << " +/- " << DTHETAe_SC_RMS[iSC] << std::endl;
  std::cout << " iSC = " << iSC << " DPsi =   " << DPSIe_SC_Mean[iSC]   << " +/- " << DPSIe_SC_RMS[iSC]   << std::endl;
  std::cout << " iSC = " << iSC << " DX =     " << DX_SC_Mean[iSC]      << " +/- " << DX_SC_RMS[iSC]      << std::endl;
  std::cout << " iSC = " << iSC << " DY =     " << DY_SC_Mean[iSC]      << " +/- " << DY_SC_RMS[iSC]      << std::endl;
  std::cout << " iSC = " << iSC << " DZ =     " << DZ_SC_Mean[iSC]      << " +/- " << DZ_SC_RMS[iSC]      << std::endl;
  std::cout << "============================================================================" << std::endl;
  std::cout << "============================================================================" << std::endl;
  std::cout << "============================================================================" << std::endl;
  
 }