// -*- C++ -*-
#include "Rivet/Analysis.hh"
#include "Rivet/Projections/FinalState.hh"
#include "Rivet/Projections/FastJets.hh"
#include "Rivet/Projections/DressedLeptons.hh"
#include "Rivet/Projections/MissingMomentum.hh"
#include "Rivet/Projections/PromptFinalState.hh"
#include "Rivet/Tools/AliceCommon.hh"
#include "Rivet/Projections/AliceCommon.hh"
#include "Rivet/Projections/UnstableParticles.hh"

namespace Rivet {


  /// @brief Strange meson production at 5 TeV
  class ALICE_2018_I1669819 : public Analysis {
  public:

    /// Constructor
    RIVET_DEFAULT_ANALYSIS_CTOR(ALICE_2018_I1669819);

    void BuildAverage(Scatter2DPtr AvgScatter, Histo1DPtr AvgHisto, const vector<Scatter2DPtr> Histograms) {
      for (auto& pointAvg : AvgHisto->bins()) {
        double ValWeight = 0.0;
        double WeightTot = 0.0;
        double ErrWeight = 0.0;

        for (auto histo : Histograms)
        {

            for (const auto& pointD : histo->points())
            {

                if (pointD.x() >= pointAvg.xMin() && pointD.x() < pointAvg.xMax())
                {
                    double relErr = pointD.yErrPlus() / pointD.y();
                    double weight = 1 / std::pow(relErr, 2);

                    ValWeight += pointD.y()*weight;
                    ErrWeight += std::pow(pointD.yErrPlus()*weight, 2);

                    WeightTot += weight;

                }
            }
        }

        double avg;
        double AvgErr;

        avg = ValWeight / WeightTot;
        AvgErr = std::sqrt(ErrWeight) / WeightTot;

        AvgScatter->addPoint(pointAvg.xMid(), avg, pointAvg.xWidth()/2., AvgErr);
      }
    }

    void DivideScatter2D(Scatter2DPtr s1, Scatter2DPtr s2, Scatter2DPtr s) {
        for(unsigned int i = 0; i < s2->numPoints(); i++)
        {
            if(s2->point(i).y() == 0)
            {
                s->addPoint(s2->point(i).x(), std::numeric_limits<double>::quiet_NaN());
                continue;
            }

            double yErr = (s1->point(i).y()/s2->point(i).y())*std::sqrt(std::pow(s1->point(i).yErrPlus()/s1->point(i).y(), 2) + std::pow(s2->point(i).yErrPlus()/s2->point(i).y(), 2));

            s->addPoint(s2->point(i).x(), s1->point(i).y()/s2->point(i).y(), s1->point(i).xErrPlus(), yErr);
        }

    }



    /// @name Analysis methods
    ///@{

    /// Book histograms and initialise projections before the run
    void init() {

      // Initialise and register projections

      declareCentrality(ALICE::V0MMultiplicity(), "ALICE_2015_PBPBCentrality", "V0M","V0M");

      const ALICE::PrimaryParticles app(Cuts::abseta < 0.8 && Cuts::pT > 1.*GeV && Cuts::abscharge > 0);
      declare(app, "app");

      const UnstableParticles ufsD0(Cuts::absrap < 0.5 && Cuts::pT > 1.*GeV && Cuts::abspid == 421);
      declare(ufsD0, "ufsD0");

      const UnstableParticles ufsDplus(Cuts::absrap < 0.5 && Cuts::pT > 2.*GeV && Cuts::abspid == 411);
      declare(ufsDplus, "ufsDplus");

      const UnstableParticles ufsDstar(Cuts::absrap < 0.5 && Cuts::pT > 1.*GeV && Cuts::abspid == 413);
      declare(ufsDstar, "ufsDstar");

      const UnstableParticles ufsDs(Cuts::absrap < 0.5 && Cuts::pT > 2.*GeV && Cuts::abspid == 431);
      declare(ufsDs, "ufsDs");

      book(_h["D0Pt_0010"], 1, 1, 1);
      book(_h["DplusPt_0010"], 2, 1, 1);
      book(_h["DstarPt_0010"], 3, 1, 1);
      book(_h["DsPt_0010"], 4, 1, 1);

      book(_h["D0Pt_3050"], 5, 1, 1);
      book(_h["DplusPt_3050"], 6, 1, 1);
      book(_h["DstarPt_3050"], 7, 1, 1);
      book(_h["DsPt_3050"], 8, 1, 1);

      book(_h["D0Pt_6080"], 9, 1, 1);
      book(_h["DplusPt_6080"], 10, 1, 1);
      book(_h["DstarPt_6080"], 11, 1, 1);
      book(_h["DsPt_6080"], 12, 1, 1);

      //0-10% centrality
      string refname13 = mkAxisCode(13, 1, 1);
      const Scatter2D& refdata13 = refData(refname13);
      book(_h["Ratio13_Dplus"], "_" + refname13 + "_Dplus", refdata13);
      book(_h["Ratio13_D0"], "_" + refname13 + "_D0", refdata13);
      book(_s["Ratio13_Dplus_D0"], refname13);

      string refname14 = mkAxisCode(14, 1, 1);
      const Scatter2D& refdata14 = refData(refname14);
      book(_h["Ratio14_Dstar"], "_" + refname14 + "_Dstar", refdata14);
      book(_h["Ratio14_D0"], "_" + refname14 + "_D0", refdata14);
      book(_s["Ratio14_Dstar_D0"], refname14);

      string refname15 = mkAxisCode(15, 1, 1);
      const Scatter2D& refdata15 = refData(refname15);
      book(_h["Ratio15_Ds"], "_" + refname15 + "_Ds", refdata15);
      book(_h["Ratio15_D0"], "_" + refname15 + "_D0", refdata15);
      book(_s["Ratio15_Ds_D0"], refname15);

      string refname16 = mkAxisCode(16, 1, 1);
      const Scatter2D& refdata16 = refData(refname16);
      book(_h["Ratio16_Ds"], "_" + refname16 + "_Ds", refdata16);
      book(_h["Ratio16_Dplus"], "_" + refname16 + "_Dplus", refdata16);
      book(_s["Ratio16_Ds_Dplus"], refname16);

      //30-50% centrality
      string refname17 = mkAxisCode(17, 1, 1);
      const Scatter2D& refdata17 = refData(refname17);
      book(_h["Ratio17_Dplus"], "_" + refname17 + "_Dplus", refdata17);
      book(_h["Ratio17_D0"], "_" + refname17 + "_D0", refdata17);
      book(_s["Ratio17_Dplus_D0"], refname17);

      string refname18 = mkAxisCode(18, 1, 1);
      const Scatter2D& refdata18 = refData(refname18);
      book(_h["Ratio18_Dstar"], "_" + refname18 + "_Dstar", refdata18);
      book(_h["Ratio18_D0"], "_" + refname18 + "_D0", refdata18);
      book(_s["Ratio18_Dstar_D0"], refname18);

      string refname19 = mkAxisCode(19, 1, 1);
      const Scatter2D& refdata19 = refData(refname19);
      book(_h["Ratio19_Ds"], "_" + refname19 + "_Ds", refdata19);
      book(_h["Ratio19_D0"], "_" + refname19 + "_D0", refdata19);
      book(_s["Ratio19_Ds_D0"], refname19);

      string refname20 = mkAxisCode(20, 1, 1);
      const Scatter2D& refdata20 = refData(refname20);
      book(_h["Ratio20_Ds"], "_" + refname20 + "_Ds", refdata20);
      book(_h["Ratio20_Dplus"], "_" + refname20 + "_Dplus", refdata20);
      book(_s["Ratio20_Ds_Dplus"], refname20);

      //60-80% centrality
      string refname21 = mkAxisCode(21, 1, 1);
      const Scatter2D& refdata21 = refData(refname21);
      book(_h["Ratio21_Dplus"], "_" + refname21 + "_Dplus", refdata21);
      book(_h["Ratio21_D0"], "_" + refname21 + "_D0", refdata21);
      book(_s["Ratio21_Dplus_D0"], refname21);

      string refname22 = mkAxisCode(22, 1, 1);
      const Scatter2D& refdata22 = refData(refname22);
      book(_h["Ratio22_Dstar"], "_" + refname22 + "_Dstar", refdata22);
      book(_h["Ratio22_D0"], "_" + refname22 + "_D0", refdata22);
      book(_s["Ratio22_Dstar_D0"], refname22);

      string refname23 = mkAxisCode(23, 1, 1);
      const Scatter2D& refdata23 = refData(refname23);
      book(_h["Ratio23_Ds"], "_" + refname23 + "_Ds", refdata23);
      book(_h["Ratio23_D0"], "_" + refname23 + "_D0", refdata23);
      book(_s["Ratio23_Ds_D0"], refname23);

      string refname24 = mkAxisCode(24, 1, 1);
      const Scatter2D& refdata24 = refData(refname24);
      book(_h["Ratio24_Ds"], "_" + refname24 + "_Ds", refdata24);
      book(_h["Ratio24_Dplus"], "_" + refname24 + "_Dplus", refdata24);
      book(_s["Ratio24_Ds_Dplus"], refname24);

      //Raa 0-10% centrality
      string refnameRaa25 = mkAxisCode(25, 1, 1);
      const Scatter2D& refdataRaa25 = refData(refnameRaa25);
      book(_h["Raa25_D0_PbPb"], "_" + refnameRaa25 + "_D0_PbPb", refdataRaa25);
      book(_h["Raa25_D0_pp"], "_" + refnameRaa25 + "_D0_pp", refdataRaa25);
      book(_s["Raa25_D0"], refnameRaa25);

      string refnameRaa26 = mkAxisCode(26, 1, 1);
      const Scatter2D& refdataRaa26 = refData(refnameRaa26);
      book(_h["Raa26_Dplus_PbPb"], "_" + refnameRaa26 + "_Dplus_PbPb", refdataRaa26);
      book(_h["Raa26_Dplus_pp"], "_" + refnameRaa26 + "_Dplus_pp", refdataRaa26);
      book(_s["Raa26_Dplus"], refnameRaa26);

      string refnameRaa27 = mkAxisCode(27, 1, 1);
      const Scatter2D& refdataRaa27 = refData(refnameRaa27);
      book(_h["Raa27_Dstar_PbPb"], "_" + refnameRaa27 + "_Dstar_PbPb", refdataRaa27);
      book(_h["Raa27_Dstar_pp"], "_" + refnameRaa27 + "_Dstar_pp", refdataRaa27);
      book(_s["Raa27_Dstar"], refnameRaa27);

      string refnameRaa28 = mkAxisCode(28, 1, 1);
      const Scatter2D& refdataRaa28 = refData(refnameRaa28);
      book(_h["Raa28_Ds_PbPb"], "_" + refnameRaa28 + "_Ds_PbPb", refdataRaa28);
      book(_h["Raa28_Ds_pp"], "_" + refnameRaa28 + "_Ds_pp", refdataRaa28);
      book(_s["Raa28_Ds"], refnameRaa28);

      string refnameRaa29 = mkAxisCode(29, 1, 1);
      const Scatter2D& refdataRaa29 = refData(refnameRaa29);
      book(_h["Raa29_Average_Aux"], "_" + refnameRaa29 + "_Aux", refdataRaa29);
      book(_s["Raa29_Average"], refnameRaa29);

      //Raa 30-50% centrality
      string refnameRaa30 = mkAxisCode(30, 1, 1);
      const Scatter2D& refdataRaa30 = refData(refnameRaa30);
      book(_h["Raa30_D0_PbPb"], "_" + refnameRaa30 + "_D0_PbPb", refdataRaa30);
      book(_h["Raa30_D0_pp"], "_" + refnameRaa30 + "_D0_pp", refdataRaa30);
      book(_s["Raa30_D0"], refnameRaa30);

      string refnameRaa31 = mkAxisCode(31, 1, 1);
      const Scatter2D& refdataRaa31 = refData(refnameRaa31);
      book(_h["Raa31_Dplus_PbPb"], "_" + refnameRaa31 + "_Dplus_PbPb", refdataRaa31);
      book(_h["Raa31_Dplus_pp"], "_" + refnameRaa31 + "_Dplus_pp", refdataRaa31);
      book(_s["Raa31_Dplus"], refnameRaa31);

      string refnameRaa32 = mkAxisCode(32, 1, 1);
      const Scatter2D& refdataRaa32 = refData(refnameRaa32);
      book(_h["Raa32_Dstar_PbPb"], "_" + refnameRaa32 + "_Dstar_PbPb", refdataRaa32);
      book(_h["Raa32_Dstar_pp"], "_" + refnameRaa32 + "_Dstar_pp", refdataRaa32);
      book(_s["Raa32_Dstar"], refnameRaa32);

      string refnameRaa33 = mkAxisCode(33, 1, 1);
      const Scatter2D& refdataRaa33 = refData(refnameRaa33);
      book(_h["Raa33_Ds_PbPb"], "_" + refnameRaa33 + "_Ds_PbPb", refdataRaa33);
      book(_h["Raa33_Ds_pp"], "_" + refnameRaa33 + "_Ds_pp", refdataRaa33);
      book(_s["Raa33_Ds"], refnameRaa33);

      string refnameRaa34 = mkAxisCode(34, 1, 1);
      const Scatter2D& refdataRaa34 = refData(refnameRaa34);
      book(_h["Raa34_Average_Aux"], "_" + refnameRaa34 + "_Aux", refdataRaa34);
      book(_s["Raa34_Average"], refnameRaa34);

      //Raa 60-80% centrality
      string refnameRaa35 = mkAxisCode(35, 1, 1);
      const Scatter2D& refdataRaa35 = refData(refnameRaa35);
      book(_h["Raa35_D0_PbPb"], "_" + refnameRaa35 + "_D0_PbPb", refdataRaa35);
      book(_h["Raa35_D0_pp"], "_" + refnameRaa35 + "_D0_pp", refdataRaa35);
      book(_s["Raa35_D0"], refnameRaa35);

      string refnameRaa36 = mkAxisCode(36, 1, 1);
      const Scatter2D& refdataRaa36 = refData(refnameRaa36);
      book(_h["Raa36_Dplus_PbPb"], "_" + refnameRaa36 + "_Dplus_PbPb", refdataRaa36);
      book(_h["Raa36_Dplus_pp"], "_" + refnameRaa36 + "_Dplus_pp", refdataRaa36);
      book(_s["Raa36_Dplus"], refnameRaa36);

      string refnameRaa37 = mkAxisCode(37, 1, 1);
      const Scatter2D& refdataRaa37 = refData(refnameRaa37);
      book(_h["Raa37_Dstar_PbPb"], "_" + refnameRaa37 + "_Dstar_PbPb", refdataRaa37);
      book(_h["Raa37_Dstar_pp"], "_" + refnameRaa37 + "_Dstar_pp", refdataRaa37);
      book(_s["Raa37_Dstar"], refnameRaa37);

      string refnameRaa38 = mkAxisCode(38, 1, 1);
      const Scatter2D& refdataRaa38 = refData(refnameRaa38);
      book(_h["Raa38_Ds_PbPb"], "_" + refnameRaa38 + "_Ds_PbPb", refdataRaa38);
      book(_h["Raa38_Ds_pp"], "_" + refnameRaa38 + "_Ds_pp", refdataRaa38);
      book(_s["Raa38_Ds"], refnameRaa38);

      string refnameRaa39 = mkAxisCode(39, 1, 1);
      const Scatter2D& refdataRaa39 = refData(refnameRaa39);
      book(_h["Raa39_Average_Aux"], "_" + refnameRaa39 + "_Aux", refdataRaa39);
      book(_s["Raa39_Average"], refnameRaa39);

      //Table 40 is PbPb 2.76 TeV

      vector<double> D0bins = {1., 2., 3., 4., 5., 6., 8., 12., 16., 24.};
      vector<double> Dplusbins = {3., 4., 5., 6., 8., 12., 16., 24., 36.};
      vector<double> Dstarbins = {3., 4., 5., 6., 8., 12., 16., 24., 36.};

      book(_h["Raa40_D0_PbPb"], "_Raa40_D0_PbPb", D0bins);
      book(_h["Raa40_D0_pp"], "_Raa40_D0_pp", D0bins);
      book(_s["Raa40_D0"], "_Raa40_D0");

      book(_h["Raa40_Dplus_PbPb"], "_Raa40_Dplus_PbPb", Dplusbins);
      book(_h["Raa40_Dplus_pp"], "_Raa40_Dplus_pp", Dplusbins);
      book(_s["Raa40_Dplus"], "_Raa40_Dplus");

      book(_h["Raa40_Dstar_PbPb"], "_Raa40_Dstar_PbPb", Dstarbins);
      book(_h["Raa40_Dstar_pp"], "_Raa40_Dstar_pp", Dstarbins);
      book(_s["Raa40_Dstar"], "_Raa40_Dstar");

      string refnameRaa40 = mkAxisCode(40, 1, 1);
      const Scatter2D& refdataRaa40 = refData(refnameRaa40);
      book(_h["Raa40_Average_Aux"], "_" + refnameRaa40 + "_Aux", refdataRaa40);
      book(_s["Raa40_Average"],refnameRaa40);

      string refnameRaa41 = mkAxisCode(41, 1, 1);
      const Scatter2D& refdataRaa41 = refData(refnameRaa41);
      book(_h["Raa41_chParticles_PbPb"], "_" + refnameRaa41 + "_PbPb", refdataRaa41);
      book(_h["Raa41_chParticles_pp"], "_" + refnameRaa41 + "_pp", refdataRaa41);
      book(_s["Raa41_chParticles"], "_Raa_chParticles",refnameRaa41);
      book(_s["Raa41_AvgD_chParticles"],refnameRaa41);

      string refnameRaa42 = mkAxisCode(42, 1, 1);
      const Scatter2D& refdataRaa42 = refData(refnameRaa42);
      book(_h["Raa42_chParticles_PbPb"], "_" + refnameRaa42 + "_PbPb", refdataRaa42);
      book(_h["Raa42_chParticles_pp"], "_" + refnameRaa42 + "_pp", refdataRaa42);
      book(_s["Raa42_chParticles"], "_Raa_chParticles42",refnameRaa42);
      book(_s["Raa42_AvgD_chParticles"],refnameRaa42);

      string refnameRaa43 = mkAxisCode(43, 1, 1);
      const Scatter2D& refdataRaa43 = refData(refnameRaa43);
      book(_h["Raa43_chParticles_PbPb"], "_" + refnameRaa43 + "_PbPb", refdataRaa43);
      book(_h["Raa43_chParticles_pp"], "_" + refnameRaa43 + "_pp", refdataRaa43);
      book(_s["Raa43_chParticles"], "_Raa_chParticles43",refnameRaa43);
      book(_s["Raa43_AvgD_chParticles"],refnameRaa43);

      book(_c["sow_pp5TeV"], "_sow_pp5TeV");
      book(_c["sow_PbPb5TeV_0010"], "_sow_PbPb5TeV_0010");
      book(_c["sow_PbPb5TeV_3050"], "_sow_PbPb5TeV_3050");
      book(_c["sow_PbPb5TeV_6080"], "_sow_PbPb5TeV_6080");

      book(_c["sow_pp2TeV"], "_sow_pp2TeV");
      book(_c["sow_PbPb2TeV"], "_sow_PbPb2TeV");


    }


    /// Perform the per-event analysis
    void analyze(const Event& event) {

      const ParticlePair& beam = beams();
      string CollSystem = "Empty";
      double NN = 208;

      if (beam.first.pid() == PID::LEAD && beam.second.pid() == PID::LEAD)
      {
          CollSystem = "PBPB";
          if(fuzzyEquals(sqrtS()/GeV, 2760*NN, 1E-3)) CollSystem += "2TeV";
          else if(fuzzyEquals(sqrtS()/GeV, 5020*NN, 1E-3)) CollSystem += "5TeV";
      }
      if (beam.first.pid() == PID::PROTON && beam.second.pid() == PID::PROTON)
      {
          CollSystem = "PP";
          if(fuzzyEquals(sqrtS()/GeV, 2760, 1E-3)) CollSystem += "2TeV";
          else if(fuzzyEquals(sqrtS()/GeV, 5020, 1E-3)) CollSystem += "5TeV";
      }

      Particles particlesD0 = apply<UnstableParticles>(event,"ufsD0").particles();
      Particles particlesDplus = apply<UnstableParticles>(event,"ufsDplus").particles();
      Particles particlesDstar = apply<UnstableParticles>(event,"ufsDstar").particles();
      Particles particlesDs = apply<UnstableParticles>(event,"ufsDs").particles();
      Particles chParticles = apply<ALICE::PrimaryParticles>(event, "app").particles();


      if(CollSystem == "PP5TeV")
      {
          _c["sow_pp5TeV"]->fill();

          for(const Particle& p : particlesD0)
          {
              if(p.fromBottom()) continue;
              _h["Raa25_D0_pp"]->fill(p.pT()/GeV);
              _h["Raa30_D0_pp"]->fill(p.pT()/GeV);
              _h["Raa35_D0_pp"]->fill(p.pT()/GeV);
          }

          for(const Particle& p : particlesDplus)
          {
              if(p.fromBottom()) continue;
              _h["Raa26_Dplus_pp"]->fill(p.pT()/GeV);
              _h["Raa31_Dplus_pp"]->fill(p.pT()/GeV);
              _h["Raa36_Dplus_pp"]->fill(p.pT()/GeV);
          }

          for(const Particle& p : particlesDstar)
          {
              if(p.fromBottom()) continue;
              _h["Raa27_Dstar_pp"]->fill(p.pT()/GeV);
              _h["Raa32_Dstar_pp"]->fill(p.pT()/GeV);
              _h["Raa37_Dstar_pp"]->fill(p.pT()/GeV);
          }

          for(const Particle& p : particlesDs)
          {
              if(p.fromBottom()) continue;
              _h["Raa28_Ds_pp"]->fill(p.pT()/GeV);
              _h["Raa33_Ds_pp"]->fill(p.pT()/GeV);
              _h["Raa38_Ds_pp"]->fill(p.pT()/GeV);
          }

          for(const Particle& p : chParticles)
          {
              _h["Raa41_chParticles_pp"]->fill(p.pT()/GeV);
              _h["Raa42_chParticles_pp"]->fill(p.pT()/GeV);
              _h["Raa43_chParticles_pp"]->fill(p.pT()/GeV);
          }

      }

      if(CollSystem == "PP2TeV")
      {
          _c["sow_pp2TeV"]->fill();

          for(const Particle& p : particlesD0)
          {
              if(p.fromBottom()) continue;
              _h["Raa40_D0_pp"]->fill(p.pT()/GeV);
          }

          for(const Particle& p : particlesDplus)
          {
              if(p.fromBottom()) continue;
              _h["Raa40_Dplus_pp"]->fill(p.pT()/GeV);
          }

          for(const Particle& p : particlesDstar)
          {
              if(p.fromBottom()) continue;
              _h["Raa40_Dstar_pp"]->fill(p.pT()/GeV);
          }

      }


      // The centrality projection.
      const CentralityProjection& centProj = apply<CentralityProjection>(event,"V0M");

      // The centrality.
      const double cent = centProj();

      if(cent >= 80.) vetoEvent;

      if(CollSystem == "PBPB5TeV")
      {
          if(cent < 10.)
          {
              _c["sow_PbPb5TeV_0010"]->fill();
              for(const Particle& p : particlesD0)
              {
                  if(p.fromBottom()) continue;
                  _h["D0Pt_0010"]->fill(p.pT()/GeV);
                  _h["Ratio13_D0"]->fill(p.pT()/GeV);
                  _h["Ratio14_D0"]->fill(p.pT()/GeV);
                  _h["Ratio15_D0"]->fill(p.pT()/GeV);
                  _h["Raa25_D0_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : particlesDplus)
              {
                  if(p.fromBottom()) continue;
                  _h["DplusPt_0010"]->fill(p.pT()/GeV);
                  _h["Ratio13_Dplus"]->fill(p.pT()/GeV);
                  _h["Ratio16_Dplus"]->fill(p.pT()/GeV);
                  _h["Raa26_Dplus_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : particlesDstar)
              {
                  if(p.fromBottom()) continue;
                  _h["DstarPt_0010"]->fill(p.pT()/GeV);
                  _h["Ratio14_Dstar"]->fill(p.pT()/GeV);
                  _h["Raa27_Dstar_PbPb"]->fill(p.pT()/GeV);

              }

              for(const Particle& p : particlesDs)
              {
                  if(p.fromBottom()) continue;
                  _h["DsPt_0010"]->fill(p.pT()/GeV);
                  _h["Ratio15_Ds"]->fill(p.pT()/GeV);
                  _h["Ratio16_Ds"]->fill(p.pT()/GeV);
                  _h["Raa28_Ds_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : chParticles)
              {
                  _h["Raa41_chParticles_PbPb"]->fill(p.pT()/GeV);
              }

          }
          else if(cent >= 30. && cent < 50.)
          {
              _c["sow_PbPb5TeV_3050"]->fill();
              for(const Particle& p : particlesD0)
              {
                  if(p.fromBottom()) continue;
                  _h["D0Pt_3050"]->fill(p.pT()/GeV);
                  _h["Ratio17_D0"]->fill(p.pT()/GeV);
                  _h["Ratio18_D0"]->fill(p.pT()/GeV);
                  _h["Ratio19_D0"]->fill(p.pT()/GeV);
                  _h["Raa30_D0_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : particlesDplus)
              {
                  if(p.fromBottom()) continue;
                  _h["DplusPt_3050"]->fill(p.pT()/GeV);
                  _h["Ratio17_Dplus"]->fill(p.pT()/GeV);
                  _h["Ratio20_Dplus"]->fill(p.pT()/GeV);
                  _h["Raa31_Dplus_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : particlesDstar)
              {
                  if(p.fromBottom()) continue;
                  _h["DstarPt_3050"]->fill(p.pT()/GeV);
                  _h["Ratio18_Dstar"]->fill(p.pT()/GeV);
                  _h["Raa32_Dstar_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : particlesDs)
              {
                  if(p.fromBottom()) continue;
                  _h["DsPt_3050"]->fill(p.pT()/GeV);
                  _h["Ratio19_Ds"]->fill(p.pT()/GeV);
                  _h["Ratio20_Ds"]->fill(p.pT()/GeV);
                  _h["Raa33_Ds_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : chParticles)
              {
                  _h["Raa42_chParticles_PbPb"]->fill(p.pT()/GeV);
              }
          }
          else if(cent >= 60. && cent < 80.)
          {
              _c["sow_PbPb5TeV_6080"]->fill();
              for(const Particle& p : particlesD0)
              {
                  if(p.fromBottom()) continue;
                  _h["D0Pt_6080"]->fill(p.pT()/GeV);
                  _h["Ratio21_D0"]->fill(p.pT()/GeV);
                  _h["Ratio22_D0"]->fill(p.pT()/GeV);
                  _h["Ratio23_D0"]->fill(p.pT()/GeV);
                  _h["Raa35_D0_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : particlesDplus)
              {
                  if(p.fromBottom()) continue;
                  _h["DplusPt_6080"]->fill(p.pT()/GeV);
                  _h["Ratio21_Dplus"]->fill(p.pT()/GeV);
                  _h["Ratio24_Dplus"]->fill(p.pT()/GeV);
                  _h["Raa36_Dplus_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : particlesDstar)
              {
                  if(p.fromBottom()) continue;
                  _h["DstarPt_6080"]->fill(p.pT()/GeV);
                  _h["Ratio22_Dstar"]->fill(p.pT()/GeV);
                  _h["Raa37_Dstar_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : particlesDs)
              {
                  if(p.fromBottom()) continue;
                  _h["DsPt_6080"]->fill(p.pT()/GeV);
                  _h["Ratio23_Ds"]->fill(p.pT()/GeV);
                  _h["Ratio24_Ds"]->fill(p.pT()/GeV);
                  _h["Raa38_Ds_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : chParticles)
              {
                  _h["Raa43_chParticles_PbPb"]->fill(p.pT()/GeV);
              }

          }
      }

      if(CollSystem == "PBPB2TeV")
      {
          if(cent < 10.)
          {
              _c["sow_PbPb2TeV"]->fill();
              for(const Particle& p : particlesD0)
              {
                  if(p.fromBottom()) continue;
                  _h["Raa40_D0_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : particlesDplus)
              {
                  if(p.fromBottom()) continue;
                  _h["Raa40_Dplus_PbPb"]->fill(p.pT()/GeV);
              }

              for(const Particle& p : particlesDstar)
              {
                  if(p.fromBottom()) continue;
                  _h["Raa40_Dstar_PbPb"]->fill(p.pT()/GeV);
              }
          }
      }

    }


    /// Normalise histograms etc., after the run
    void finalize() {

      //2.76 TeV
      _h["Raa40_D0_PbPb"]->scaleW(1./_c["sow_PbPb2TeV"]->sumW());
      _h["Raa40_D0_pp"]->scaleW(Ncoll0010/_c["sow_pp2TeV"]->sumW());
      divide(_h["Raa40_D0_PbPb"], _h["Raa40_D0_pp"], _s["Raa40_D0"]);

      _h["Raa40_Dplus_PbPb"]->scaleW(1./_c["sow_PbPb2TeV"]->sumW());
      _h["Raa40_Dplus_pp"]->scaleW(Ncoll0010/_c["sow_pp2TeV"]->sumW());
      divide(_h["Raa40_Dplus_PbPb"], _h["Raa40_Dplus_pp"], _s["Raa40_Dplus"]);

      _h["Raa40_Dstar_PbPb"]->scaleW(1./_c["sow_PbPb2TeV"]->sumW());
      _h["Raa40_Dstar_pp"]->scaleW(Ncoll0010/_c["sow_pp2TeV"]->sumW());
      divide(_h["Raa40_Dstar_PbPb"], _h["Raa40_Dstar_pp"], _s["Raa40_Dstar"]);
      vector<Scatter2DPtr> Histograms40 = {_s["Raa40_D0"], _s["Raa40_Dplus"], _s["Raa40_Dstar"]};
      BuildAverage(_s["Raa40_Average"], _h["Raa40_Average_Aux"], Histograms40);

      //5.02 TeV
      _h["D0Pt_0010"]->scaleW(1./(2*_c["sow_PbPb5TeV_0010"]->sumW()));
      _h["DplusPt_0010"]->scaleW(1./(2*_c["sow_PbPb5TeV_0010"]->sumW()));
      _h["DstarPt_0010"]->scaleW(1./(2*_c["sow_PbPb5TeV_0010"]->sumW()));
      _h["DsPt_0010"]->scaleW(1./(2*_c["sow_PbPb5TeV_0010"]->sumW()));

      _h["D0Pt_3050"]->scaleW(1./(2*_c["sow_PbPb5TeV_3050"]->sumW()));
      _h["DplusPt_3050"]->scaleW(1./(2*_c["sow_PbPb5TeV_3050"]->sumW()));
      _h["DstarPt_3050"]->scaleW(1./(2*_c["sow_PbPb5TeV_3050"]->sumW()));
      _h["DsPt_3050"]->scaleW(1./(2*_c["sow_PbPb5TeV_3050"]->sumW()));

      _h["D0Pt_6080"]->scaleW(1./(2*_c["sow_PbPb5TeV_6080"]->sumW()));
      _h["DplusPt_6080"]->scaleW(1./(2*_c["sow_PbPb5TeV_6080"]->sumW()));
      _h["DstarPt_6080"]->scaleW(1./(2*_c["sow_PbPb5TeV_6080"]->sumW()));
      _h["DsPt_6080"]->scaleW(1./(2*_c["sow_PbPb5TeV_6080"]->sumW()));

      //0-10%
      divide(_h["Ratio13_Dplus"], _h["Ratio13_D0"], _s["Ratio13_Dplus_D0"]);
      divide(_h["Ratio14_Dstar"], _h["Ratio14_D0"], _s["Ratio14_Dstar_D0"]);
      divide(_h["Ratio15_Ds"], _h["Ratio15_D0"], _s["Ratio15_Ds_D0"]);
      divide(_h["Ratio16_Ds"], _h["Ratio16_Dplus"], _s["Ratio16_Ds_Dplus"]);

      //30-50%
      divide(_h["Ratio17_Dplus"], _h["Ratio17_D0"], _s["Ratio17_Dplus_D0"]);
      divide(_h["Ratio18_Dstar"], _h["Ratio18_D0"], _s["Ratio18_Dstar_D0"]);
      divide(_h["Ratio19_Ds"], _h["Ratio19_D0"], _s["Ratio19_Ds_D0"]);
      divide(_h["Ratio20_Ds"], _h["Ratio20_Dplus"], _s["Ratio20_Ds_Dplus"]);

      //60-80%
      divide(_h["Ratio21_Dplus"], _h["Ratio21_D0"], _s["Ratio21_Dplus_D0"]);
      divide(_h["Ratio22_Dstar"], _h["Ratio22_D0"], _s["Ratio22_Dstar_D0"]);
      divide(_h["Ratio23_Ds"], _h["Ratio23_D0"], _s["Ratio23_Ds_D0"]);
      divide(_h["Ratio24_Ds"], _h["Ratio24_Dplus"], _s["Ratio24_Ds_Dplus"]);

      //Raa 0-10%
      _h["Raa25_D0_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_0010"]->sumW());
      _h["Raa25_D0_pp"]->scaleW(Ncoll0010/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa25_D0_PbPb"], _h["Raa25_D0_pp"], _s["Raa25_D0"]);

      _h["Raa26_Dplus_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_0010"]->sumW());
      _h["Raa26_Dplus_pp"]->scaleW(Ncoll0010/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa26_Dplus_PbPb"], _h["Raa26_Dplus_pp"], _s["Raa26_Dplus"]);

      _h["Raa27_Dstar_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_0010"]->sumW());
      _h["Raa27_Dstar_pp"]->scaleW(Ncoll0010/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa27_Dstar_PbPb"], _h["Raa27_Dstar_pp"], _s["Raa27_Dstar"]);

      _h["Raa28_Ds_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_0010"]->sumW());
      _h["Raa28_Ds_pp"]->scaleW(Ncoll0010/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa28_Ds_PbPb"], _h["Raa28_Ds_pp"], _s["Raa28_Ds"]);

      //Raa 30-50%
      _h["Raa30_D0_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_3050"]->sumW());
      _h["Raa30_D0_pp"]->scaleW(Ncoll3050/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa30_D0_PbPb"], _h["Raa30_D0_pp"], _s["Raa30_D0"]);

      _h["Raa31_Dplus_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_3050"]->sumW());
      _h["Raa31_Dplus_pp"]->scaleW(Ncoll3050/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa31_Dplus_PbPb"], _h["Raa31_Dplus_pp"], _s["Raa31_Dplus"]);

      _h["Raa32_Dstar_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_3050"]->sumW());
      _h["Raa32_Dstar_pp"]->scaleW(Ncoll3050/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa32_Dstar_PbPb"], _h["Raa32_Dstar_pp"], _s["Raa32_Dstar"]);

      _h["Raa33_Ds_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_3050"]->sumW());
      _h["Raa33_Ds_pp"]->scaleW(Ncoll3050/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa33_Ds_PbPb"], _h["Raa33_Ds_pp"], _s["Raa33_Ds"]);

      //Raa 60-80%
      _h["Raa35_D0_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_6080"]->sumW());
      _h["Raa35_D0_pp"]->scaleW(Ncoll6080/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa35_D0_PbPb"], _h["Raa35_D0_pp"], _s["Raa35_D0"]);

      _h["Raa36_Dplus_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_6080"]->sumW());
      _h["Raa36_Dplus_pp"]->scaleW(Ncoll6080/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa36_Dplus_PbPb"], _h["Raa36_Dplus_pp"], _s["Raa36_Dplus"]);

      _h["Raa37_Dstar_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_6080"]->sumW());
      _h["Raa37_Dstar_pp"]->scaleW(Ncoll6080/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa37_Dstar_PbPb"], _h["Raa37_Dstar_pp"], _s["Raa37_Dstar"]);

      _h["Raa38_Ds_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_6080"]->sumW());
      _h["Raa38_Ds_pp"]->scaleW(Ncoll6080/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa38_Ds_PbPb"], _h["Raa38_Ds_pp"], _s["Raa38_Ds"]);

      vector<Scatter2DPtr> Histograms29 = {_s["Raa25_D0"], _s["Raa26_Dplus"], _s["Raa27_Dstar"]};
      BuildAverage(_s["Raa29_Average"], _h["Raa29_Average_Aux"], Histograms29);

      vector<Scatter2DPtr> Histograms34 = {_s["Raa30_D0"], _s["Raa31_Dplus"], _s["Raa32_Dstar"]};
      BuildAverage(_s["Raa34_Average"], _h["Raa34_Average_Aux"], Histograms34);

      vector<Scatter2DPtr> Histograms39 = {_s["Raa35_D0"], _s["Raa36_Dplus"], _s["Raa37_Dstar"]};
      BuildAverage(_s["Raa39_Average"], _h["Raa39_Average_Aux"], Histograms39);

      _h["Raa41_chParticles_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_0010"]->sumW());
      _h["Raa41_chParticles_pp"]->scaleW(Ncoll0010/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa41_chParticles_PbPb"], _h["Raa41_chParticles_pp"], _s["Raa41_chParticles"]);
      DivideScatter2D(_s["Raa29_Average"], _s["Raa41_chParticles"], _s["Raa41_AvgD_chParticles"]);

      _h["Raa42_chParticles_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_3050"]->sumW());
      _h["Raa42_chParticles_pp"]->scaleW(Ncoll3050/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa42_chParticles_PbPb"], _h["Raa42_chParticles_pp"], _s["Raa42_chParticles"]);
      DivideScatter2D(_s["Raa34_Average"], _s["Raa42_chParticles"], _s["Raa42_AvgD_chParticles"]);

      _h["Raa43_chParticles_PbPb"]->scaleW(1./_c["sow_PbPb5TeV_6080"]->sumW());
      _h["Raa43_chParticles_pp"]->scaleW(Ncoll6080/_c["sow_pp5TeV"]->sumW());
      divide(_h["Raa43_chParticles_PbPb"], _h["Raa43_chParticles_pp"], _s["Raa43_chParticles"]);
      DivideScatter2D(_s["Raa39_Average"], _s["Raa43_chParticles"], _s["Raa43_AvgD_chParticles"]);

    }

    ///@}


    /// @name Histograms
    ///@{
    map<string, Histo1DPtr> _h;
    map<string, CounterPtr> _c;
    map<string, Scatter2DPtr> _s;
    const double Ncoll0010 = 1572.;
    const double Ncoll3050 = 264.8;
    const double Ncoll6080 = 28.31;
    ///@}


  };


  RIVET_DECLARE_PLUGIN(ALICE_2018_I1669819);

}
