<commit_before>#include <RooFitHS3/RooJSONFactoryWSTool.h>

#include <RooDataHist.h>
#include <RooProdPdf.h>
#include <RooAddPdf.h>
#include <RooSimultaneous.h>
#include <RooCategory.h>
#include <RooHistFunc.h>
#include <RooWorkspace.h>

#include <TH1.h>

#include "JSONInterface.h"
#include "static_execute.h"

using RooFit::Detail::JSONNode;

///////////////////////////////////////////////////////////////////////////////////////////////////////
// individually implemented importers
///////////////////////////////////////////////////////////////////////////////////////////////////////

namespace {

class RooProdPdfFactory : public RooJSONFactoryWSTool::Importer {
public:
   virtual bool importPdf(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
   {
      std::string name(RooJSONFactoryWSTool::name(p));
      RooArgSet factors;
      if (!p.has_child("factors")) {
         RooJSONFactoryWSTool::error("no pdfs of '" + name + "'");
      }
      if (!p["factors"].is_seq()) {
         RooJSONFactoryWSTool::error("pdfs '" + name + "' are not a list.");
      }
      for (const auto &comp : p["factors"].children()) {
         std::string pdfname(comp.val());
         RooAbsPdf *pdf = tool->workspace()->pdf(pdfname.c_str());
         if (!pdf) {
            RooJSONFactoryWSTool::error("unable to obtain component '" + pdfname + "' of '" + name + "'.");
         }
         factors.add(*pdf);
      }
      RooProdPdf prod(name.c_str(), name.c_str(), factors);
      tool->workspace()->import(prod);
      return true;
   }
};

class RooAddPdfFactory : public RooJSONFactoryWSTool::Importer {
public:
   virtual bool importPdf(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
   {
      std::string name(RooJSONFactoryWSTool::name(p));
      RooArgList pdfs;
      RooArgList coefs;
      if (!p.has_child("summands")) {
         RooJSONFactoryWSTool::error("no summands of '" + name + "'");
      }
      if (!p["summands"].is_seq()) {
         RooJSONFactoryWSTool::error("summands '" + name + "' are not a list.");
      }
      if (!p.has_child("coefficients")) {
         RooJSONFactoryWSTool::error("no coefficients of '" + name + "'");
      }
      if (!p["coefficients"].is_seq()) {
         RooJSONFactoryWSTool::error("coefficients '" + name + "' are not a list.");
      }
      for (const auto &comp : p["summands"].children()) {
         std::string pdfname(comp.val());
         RooAbsPdf *pdf = tool->workspace()->pdf(pdfname.c_str());
         if (!pdf) {
            RooJSONFactoryWSTool::error("unable to obtain component '" + pdfname + "' of '" + name + "'.");
         }
         pdfs.add(*pdf);
      }
      for (const auto &comp : p["coefficients"].children()) {
         std::string coefname(comp.val());
         RooAbsArg *coef = tool->workspace()->arg(coefname.c_str());
         if (!coef) {
            RooJSONFactoryWSTool::error("unable to obtain component '" + coefname + "' of '" + name + "'.");
         }
         coefs.add(*coef);
      }
      RooAddPdf add(name.c_str(), name.c_str(), pdfs, coefs);
      tool->workspace()->import(add);
      return true;
   }
};

class RooSimultaneousFactory : public RooJSONFactoryWSTool::Importer {
public:
   virtual bool importPdf(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
   {
      std::string name(RooJSONFactoryWSTool::name(p));
      if (!p.has_child("channels")) {
         RooJSONFactoryWSTool::error("no channel components of '" + name + "'");
      }
      tool->importPdfs(p["channels"]);
      std::map<std::string, RooAbsPdf *> components;
      RooCategory cat("channelCat", "channelCat");
      for (const auto &comp : p["channels"].children()) {
         std::string catname(RooJSONFactoryWSTool::name(comp));
         std::string pdfname(comp.has_val() ? comp.val() : RooJSONFactoryWSTool::name(comp));
         RooAbsPdf *pdf = tool->workspace()->pdf(pdfname.c_str());
         if (!pdf) {
            RooJSONFactoryWSTool::error("unable to obtain component '" + pdfname + "' of '" + name + "'");
         }
         components[catname] = pdf;
         cat.defineType(catname.c_str());
      }
      RooSimultaneous simpdf(name.c_str(), name.c_str(), components, cat);
      tool->workspace()->import(simpdf);
      return true;
   }
};

} // namespace

///////////////////////////////////////////////////////////////////////////////////////////////////////
// specialized exporter implementations
///////////////////////////////////////////////////////////////////////////////////////////////////////

namespace {
class RooSimultaneousStreamer : public RooJSONFactoryWSTool::Exporter {
public:
   bool autoExportDependants() const override { return false; }
   virtual bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
   {
      const RooSimultaneous *sim = static_cast<const RooSimultaneous *>(func);
      elem["type"] << "simultaneous";
      auto &channels = elem["channels"];
      channels.set_map();
      const auto &indexCat = sim->indexCat();
      for (const auto &cat : indexCat) {
         const auto catname = cat.first.c_str();
         RooAbsPdf *pdf = sim->getPdf(catname);
         if (!pdf)
            RooJSONFactoryWSTool::error("no pdf found for category");
         auto &ch = channels[catname];
         tool->exportObject(pdf, ch);<commit_msg>[RF] Fix JSON export of RooSimultanous in HistFactory model<commit_after>#include <RooFitHS3/RooJSONFactoryWSTool.h>

#include <RooDataHist.h>
#include <RooProdPdf.h>
#include <RooAddPdf.h>
#include <RooSimultaneous.h>
#include <RooCategory.h>
#include <RooHistFunc.h>
#include <RooWorkspace.h>

#include <TH1.h>

#include "JSONInterface.h"
#include "static_execute.h"

using RooFit::Detail::JSONNode;

///////////////////////////////////////////////////////////////////////////////////////////////////////
// individually implemented importers
///////////////////////////////////////////////////////////////////////////////////////////////////////

namespace {

class RooProdPdfFactory : public RooJSONFactoryWSTool::Importer {
public:
   virtual bool importPdf(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
   {
      std::string name(RooJSONFactoryWSTool::name(p));
      RooArgSet factors;
      if (!p.has_child("factors")) {
         RooJSONFactoryWSTool::error("no pdfs of '" + name + "'");
      }
      if (!p["factors"].is_seq()) {
         RooJSONFactoryWSTool::error("pdfs '" + name + "' are not a list.");
      }
      for (const auto &comp : p["factors"].children()) {
         std::string pdfname(comp.val());
         RooAbsPdf *pdf = tool->workspace()->pdf(pdfname.c_str());
         if (!pdf) {
            RooJSONFactoryWSTool::error("unable to obtain component '" + pdfname + "' of '" + name + "'.");
         }
         factors.add(*pdf);
      }
      RooProdPdf prod(name.c_str(), name.c_str(), factors);
      tool->workspace()->import(prod);
      return true;
   }
};

class RooAddPdfFactory : public RooJSONFactoryWSTool::Importer {
public:
   virtual bool importPdf(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
   {
      std::string name(RooJSONFactoryWSTool::name(p));
      RooArgList pdfs;
      RooArgList coefs;
      if (!p.has_child("summands")) {
         RooJSONFactoryWSTool::error("no summands of '" + name + "'");
      }
      if (!p["summands"].is_seq()) {
         RooJSONFactoryWSTool::error("summands '" + name + "' are not a list.");
      }
      if (!p.has_child("coefficients")) {
         RooJSONFactoryWSTool::error("no coefficients of '" + name + "'");
      }
      if (!p["coefficients"].is_seq()) {
         RooJSONFactoryWSTool::error("coefficients '" + name + "' are not a list.");
      }
      for (const auto &comp : p["summands"].children()) {
         std::string pdfname(comp.val());
         RooAbsPdf *pdf = tool->workspace()->pdf(pdfname.c_str());
         if (!pdf) {
            RooJSONFactoryWSTool::error("unable to obtain component '" + pdfname + "' of '" + name + "'.");
         }
         pdfs.add(*pdf);
      }
      for (const auto &comp : p["coefficients"].children()) {
         std::string coefname(comp.val());
         RooAbsArg *coef = tool->workspace()->arg(coefname.c_str());
         if (!coef) {
            RooJSONFactoryWSTool::error("unable to obtain component '" + coefname + "' of '" + name + "'.");
         }
         coefs.add(*coef);
      }
      RooAddPdf add(name.c_str(), name.c_str(), pdfs, coefs);
      tool->workspace()->import(add);
      return true;
   }
};

class RooSimultaneousFactory : public RooJSONFactoryWSTool::Importer {
public:
   virtual bool importPdf(RooJSONFactoryWSTool *tool, const JSONNode &p) const override
   {
      std::string name(RooJSONFactoryWSTool::name(p));
      if (!p.has_child("channels")) {
         RooJSONFactoryWSTool::error("no channel components of '" + name + "'");
      }
      tool->importPdfs(p["channels"]);
      std::map<std::string, RooAbsPdf *> components;
      RooCategory cat("channelCat", "channelCat");
      for (const auto &comp : p["channels"].children()) {
         std::string catname(RooJSONFactoryWSTool::name(comp));
         std::string pdfname(comp.has_val() ? comp.val() : RooJSONFactoryWSTool::name(comp));
         RooAbsPdf *pdf = tool->workspace()->pdf(pdfname.c_str());
         if (!pdf) {
            RooJSONFactoryWSTool::error("unable to obtain component '" + pdfname + "' of '" + name + "'");
         }
         components[catname] = pdf;
         cat.defineType(catname.c_str());
      }
      RooSimultaneous simpdf(name.c_str(), name.c_str(), components, cat);
      tool->workspace()->import(simpdf);
      return true;
   }
};

} // namespace

///////////////////////////////////////////////////////////////////////////////////////////////////////
// specialized exporter implementations
///////////////////////////////////////////////////////////////////////////////////////////////////////

namespace {
class RooSimultaneousStreamer : public RooJSONFactoryWSTool::Exporter {
public:
   bool autoExportDependants() const override { return false; }
   virtual bool exportObject(RooJSONFactoryWSTool *tool, const RooAbsArg *func, JSONNode &elem) const override
   {
      const RooSimultaneous *sim = static_cast<const RooSimultaneous *>(func);
      elem["type"] << "simultaneous";
      auto &channels = elem["channels"];
      channels.set_map();
      const auto &indexCat = sim->indexCat();
      for (const auto &cat : indexCat) {
         const auto catname = cat.first.c_str();
         RooAbsPdf *pdf = sim->getPdf(catname);
         if (!pdf)
            RooJSONFactoryWSTool::error("no pdf found for category");
         tool->exportObject(pdf, channels);
{'fraction_non_alphanumeric': 0.2194034011708949, 'fraction_numerical': 0.0003717126661090977, 'mean_word_length': 2.3012269938650305, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6949867', 'n_tokens_mistral': 3255, 'n_tokens_neox': 3225, 'n_words': 632}