diff --git a/README/ReleaseNotes/v638/index.md b/README/ReleaseNotes/v638/index.md
index 328ef46d9ff86..bee35287e8efc 100644
--- a/README/ReleaseNotes/v638/index.md
+++ b/README/ReleaseNotes/v638/index.md
@@ -13,7 +13,9 @@ The following people have contributed to this new version:
  Bertrand Bellenot, CERN/EP-SFT,\
  Jakob Blomer, CERN/EP-SFT,\
  Lukas Breitwieser, CERN/EP-SFT,\
+ Carsten Burgard, University of Hamburg and TU Dortmund,\
  Philippe Canal, FNAL,\
+ Simon Cello, TU Dortmund,\
  Olivier Couet, CERN/EP-SFT,\
  Marta Czurylo, CERN/EP-SFT,\
  Florine de Geus, CERN/EP-SFT and University of Twente,\
diff --git a/roofit/roofitcore/inc/RooGlobalFunc.h b/roofit/roofitcore/inc/RooGlobalFunc.h
index 75f7dda24932c..5f4268256737c 100644
--- a/roofit/roofitcore/inc/RooGlobalFunc.h
+++ b/roofit/roofitcore/inc/RooGlobalFunc.h
@@ -358,7 +358,7 @@ RooCmdArg Conditional(const RooArgSet& pdfSet, const RooArgSet& depSet, bool dep
  * @{
  */
 // RooAbsPdf::generate arguments
-RooCmdArg ProtoData(const RooDataSet& protoData, bool randomizeOrder=false, bool resample=false) ;
+RooCmdArg ProtoData(const RooAbsData &protoData, bool randomizeOrder = false, bool resample = false);
 RooCmdArg NumEvents(Int_t numEvents) ;
 RooCmdArg NumEvents(double numEvents) ;
 RooCmdArg AutoBinned(bool flag=true) ;
diff --git a/roofit/roofitcore/src/RooAbsPdf.cxx b/roofit/roofitcore/src/RooAbsPdf.cxx
index 4e4b050f17769..983c157eeae35 100644
--- a/roofit/roofitcore/src/RooAbsPdf.cxx
+++ b/roofit/roofitcore/src/RooAbsPdf.cxx
@@ -1157,8 +1157,6 @@ RooAbsGenContext* RooAbsPdf::autoGenContext(const RooArgSet &vars, const RooData
   return context ;
 }
 
-
-
 ////////////////////////////////////////////////////////////////////////////////
 /// Generate a new dataset containing the specified variables with events sampled from our distribution.
 /// Generate the specified number of events or expectedEvents() if not specified.
@@ -1179,11 +1177,13 @@ RooAbsGenContext* RooAbsPdf::autoGenContext(const RooArgSet &vars, const RooData
 /// 
|  `Extended()`                         |  If no number of events to be generated is given,
 /// use expected number of events from extended likelihood term.
 /// This evidently only works for extended PDFs.
-///  | 
|  `GenBinned(const char* tag)`         |  Use binned generation for all component pdfs that have 'setAttribute(tag)' set
-///  | 
|  `AutoBinned(bool flag)`            |  Automatically deploy binned generation for binned distributions (e.g. RooHistPdf, sums and products of
+///  | 
|  `GenBinned(const char* tag)`         |  Use binned generation for all component pdfs that have
+/// 'setAttribute(tag)' set  | 
|  `AutoBinned(bool flag)`            |  Automatically deploy binned generation for
+/// binned distributions (e.g. RooHistPdf, sums and products of
 ///                                                 RooHistPdfs etc)
 /// \note Datasets that are generated in binned mode are returned as weighted unbinned datasets. This means that
-/// for each bin, there will be one event in the dataset with a weight corresponding to the (possibly randomised) bin content.
+/// for each bin, there will be one event in the dataset with a weight corresponding to the (possibly randomised) bin
+/// content.
 ///
 ///
 ///  | 
|  `AllBinned()`                        |  As above, but for all components.
@@ -1191,16 +1191,17 @@ RooAbsGenContext* RooAbsPdf::autoGenContext(const RooArgSet &vars, const RooData
 ///       as binned generation is always executed at the top-level node for a regular
 ///       PDF, so for those it only mattes that the top-level node is tagged.
 ///
-///  | 
|  ProtoData(const RooDataSet& data, bool randOrder)
+///  | 
|  ProtoData(const RooAbsData& data, bool randOrder)
 ///           |  Use specified dataset as prototype dataset. If randOrder in ProtoData() is set to true,
 ///               the order of the events in the dataset will be read in a random order if the requested
 ///               number of events to be generated does not match the number of events in the prototype dataset.
-///               \note If ProtoData() is used, the specified existing dataset as a prototype: the new dataset will contain
-///               the same number of events as the prototype (unless otherwise specified), and any prototype variables not in
-///               whatVars will be copied into the new dataset for each generated event and also used to set our PDF parameters.
-///               The user can specify a  number of events to generate that will override the default. The result is a
-///               copy of the prototype dataset with only variables in whatVars randomized. Variables in whatVars that
-///               are not in the prototype will be added as new columns to the generated dataset.
+///               \note If ProtoData() is used, the specified existing dataset as a prototype: the new dataset will
+///               contain the same number of events as the prototype (unless otherwise specified), and any prototype
+///               variables not in whatVars will be copied into the new dataset for each generated event and also used
+///               to set our PDF parameters. The user can specify a  number of events to generate that will override the
+///               default. The result is a copy of the prototype dataset with only variables in whatVars randomized.
+///               Variables in whatVars that are not in the prototype will be added as new columns to the generated
+///               dataset.
 ///
 /// 
 ///
diff --git a/roofit/roofitcore/src/RooBinnedGenContext.cxx b/roofit/roofitcore/src/RooBinnedGenContext.cxx
index 3a53b28e30eb9..7da5af80d7820 100644
--- a/roofit/roofitcore/src/RooBinnedGenContext.cxx
+++ b/roofit/roofitcore/src/RooBinnedGenContext.cxx
@@ -60,7 +60,7 @@ RooBinnedGenContext::RooBinnedGenContext(const RooAbsPdf &model, const RooArgSet
   if (prototype)
     {
       RooArgSet coefNSet(vars) ;
-      coefNSet.add(*prototype->get()) ;
+      coefNSet.add(*prototype->get(), true);
       _pdf->fixAddCoefNormalization(coefNSet) ;
     }
 
diff --git a/roofit/roofitcore/src/RooGenContext.cxx b/roofit/roofitcore/src/RooGenContext.cxx
index ed19687122f9d..a08f481d45c81 100644
--- a/roofit/roofitcore/src/RooGenContext.cxx
+++ b/roofit/roofitcore/src/RooGenContext.cxx
@@ -87,7 +87,7 @@ RooGenContext::RooGenContext(const RooAbsPdf &model, const RooArgSet &vars,
   // Optionally fix RooAddPdf normalizations
   if (prototype&&_pdfClone->dependsOn(*prototype->get())) {
     RooArgSet fullNormSet(vars) ;
-    fullNormSet.add(*prototype->get()) ;
+    fullNormSet.add(*prototype->get(), true);
     _pdfClone->fixAddCoefNormalization(fullNormSet) ;
   }
 
diff --git a/roofit/roofitcore/src/RooGlobalFunc.cxx b/roofit/roofitcore/src/RooGlobalFunc.cxx
index a9bd2713f6002..c4e0bfa49defb 100644
--- a/roofit/roofitcore/src/RooGlobalFunc.cxx
+++ b/roofit/roofitcore/src/RooGlobalFunc.cxx
@@ -807,7 +807,7 @@ RooCmdArg Conditional(const RooArgSet &pdfSet, const RooArgSet &depSet, bool dep
 };
 
 // RooAbsPdf::generate arguments
-RooCmdArg ProtoData(const RooDataSet &protoData, bool randomizeOrder, bool resample)
+RooCmdArg ProtoData(const RooAbsData &protoData, bool randomizeOrder, bool resample)
 {
    return RooCmdArg("PrototypeData", randomizeOrder, resample, 0, 0, nullptr, nullptr, &protoData, nullptr);
 }
diff --git a/roofit/roostats/inc/RooStats/ToyMCSampler.h b/roofit/roostats/inc/RooStats/ToyMCSampler.h
index 4da726a460a53..7967fec7705c7 100644
--- a/roofit/roostats/inc/RooStats/ToyMCSampler.h
+++ b/roofit/roostats/inc/RooStats/ToyMCSampler.h
@@ -229,14 +229,15 @@ class ToyMCSampler: public TestStatSampler {
          fAdaptiveLowLimit = low_threshold;
       }
 
-      void SetProtoData(const RooDataSet* d) { fProtoData = d; }
+      void SetProtoData(const RooAbsData *d) { fProtoData = d; }
 
    protected:
 
       const RooArgList* EvaluateAllTestStatistics(RooAbsData& data, const RooArgSet& poi, DetailedOutputAggregator& detOutAgg);
 
       /// helper for GenerateToyData
-      std::unique_ptr Generate(RooAbsPdf &pdf, RooArgSet &observables, const RooDataSet *protoData=nullptr, int forceEvents=0) const;
+      std::unique_ptr Generate(RooAbsPdf &pdf, RooArgSet &observables,
+                                           const RooAbsData *protoData = nullptr, int forceEvents = 0) const;
 
       /// helper method for clearing  the cache
       virtual void ClearCache();
@@ -272,7 +273,7 @@ class ToyMCSampler: public TestStatSampler {
       double fAdaptiveLowLimit;
       double fAdaptiveHighLimit;
 
-      const RooDataSet *fProtoData = nullptr; ///< in dev
+      const RooAbsData *fProtoData = nullptr; ///< in dev
 
       mutable NuisanceParametersSampler *fNuisanceParametersSampler = nullptr; ///SetProtoData(&data);
+      const bool dataIsBinned = dynamic_cast(fData) != nullptr;
+      toymcs->SetGenerateBinned(dataIsBinned); // if observed is RooDataHist -> generate RooDataHist toys
+
+      fDefaultSampler = toymcs;
+      fTestStatSampler = toymcs;
    }
 
 
diff --git a/roofit/roostats/src/ToyMCSampler.cxx b/roofit/roostats/src/ToyMCSampler.cxx
index 4249038bf13cc..582c8b93d18a4 100644
--- a/roofit/roostats/src/ToyMCSampler.cxx
+++ b/roofit/roostats/src/ToyMCSampler.cxx
@@ -476,27 +476,30 @@ RooAbsData* ToyMCSampler::GenerateToyData(RooArgSet& paramPoint, double& weight,
 /// or whether it should use the expected number of events. It also takes
 /// into account the option to generate a binned data set (*i.e.* RooDataHist).
 
-std::unique_ptr ToyMCSampler::Generate(RooAbsPdf &pdf, RooArgSet &observables, const RooDataSet* protoData, int forceEvents) const {
+std::unique_ptr
+ToyMCSampler::Generate(RooAbsPdf &pdf, RooArgSet &observables, const RooAbsData *protoData, int forceEvents) const
+{
 
-  if(fProtoData) {
-    protoData = fProtoData;
-    forceEvents = protoData->numEntries();
-  }
+   if (fProtoData) {
+      protoData = fProtoData;
+      forceEvents = protoData->numEntries();
+   }
 
-  std::unique_ptr data;
-  int events = forceEvents;
-  if(events == 0) events = fNEvents;
+   std::unique_ptr data;
+   int events = forceEvents;
+   if (events == 0)
+      events = fNEvents;
 
-  // cannot use multigen when the nuisance parameters change for every toy
-  bool useMultiGen = (fUseMultiGen || fgAlwaysUseMultiGen) && !fNuisanceParametersSampler;
+   // cannot use multigen when the nuisance parameters change for every toy
+   bool useMultiGen = (fUseMultiGen || fgAlwaysUseMultiGen) && !fNuisanceParametersSampler;
 
-  if (events == 0) {
-    if (!pdf.canBeExtended() || pdf.expectedEvents(observables) <= 0) {
-      std::stringstream ss;
-      ss << "ToyMCSampler: Error : pdf is not extended and number of events per toy is zero";
-      oocoutE(nullptr,InputArguments) << ss.str() << std::endl;
-      throw std::runtime_error(ss.str());
-    }
+   if (events == 0) {
+      if (!pdf.canBeExtended() || pdf.expectedEvents(observables) <= 0) {
+         std::stringstream ss;
+         ss << "ToyMCSampler: Error : pdf is not extended and number of events per toy is zero";
+         oocoutE(nullptr, InputArguments) << ss.str() << std::endl;
+         throw std::runtime_error(ss.str());
+      }
       if(fGenerateBinned) {
         if(protoData) data = std::unique_ptr{pdf.generate(observables, AllBinned(), Extended(), ProtoData(*protoData, true, true))};
         else          data = std::unique_ptr{pdf.generate(observables, AllBinned(), Extended())};
 |