3535#include < RooTFnBinding.h>
3636#include < RooWorkspace.h>
3737
38+ #include " JSONIOUtils.h"
39+
3840#include < TF1.h>
3941#include < TH1.h>
4042
@@ -237,12 +239,18 @@ class RooLogNormalFactory : public RooFit::JSONIO::Importer {
237239 {
238240 std::string name (RooJSONFactoryWSTool::name (p));
239241 RooAbsReal *x = tool->requestArg <RooAbsReal>(p, " x" );
240- RooAbsReal *mu = tool->requestArg <RooAbsReal>(p, " mu" );
241- RooAbsReal *sigma = tool->requestArg <RooAbsReal>(p, " sigma" );
242242
243- // TODO: check if the pdf was originally exported by ROOT, in which case
244- // it can be imported back without using the standard parametrization.
245- tool->wsEmplace <RooLognormal>(name, *x, *mu, *sigma, true );
243+ // Same mechanism to undo the parameter transformation as in the
244+ // RooExponentialFactory (see comments in that class for more info).
245+ const std::string muName = p[" mu" ].val ();
246+ const std::string sigmaName = p[" sigma" ].val ();
247+ const bool isTransformed = endsWith (muName, " _lognormal_log" );
248+ const std::string suffixToRemove = isTransformed ? " _lognormal_log" : " " ;
249+ RooAbsReal *mu = tool->request <RooAbsReal>(removeSuffix (muName, suffixToRemove), name);
250+ RooAbsReal *sigma = tool->request <RooAbsReal>(removeSuffix (sigmaName, suffixToRemove), name);
251+
252+ tool->wsEmplace <RooLognormal>(name, *x, *mu, *sigma, !isTransformed);
253+
246254 return true ;
247255 }
248256};
@@ -253,11 +261,45 @@ class RooExponentialFactory : public RooFit::JSONIO::Importer {
253261 {
254262 std::string name (RooJSONFactoryWSTool::name (p));
255263 RooAbsReal *x = tool->requestArg <RooAbsReal>(p, " x" );
256- RooAbsReal *c = tool->requestArg <RooAbsReal>(p, " c" );
257264
258- // TODO: check if the pdf was originally exported by ROOT, in which case
259- // it can be imported back without using the standard parametrization.
260- tool->wsEmplace <RooExponential>(name, *x, *c, true );
265+ // If the parameter name ends with the "_exponential_inverted" suffix,
266+ // this means that it was exported from a RooFit object where the
267+ // parameter first needed to be transformed on export to match the HS3
268+ // specification. But when re-importing such a parameter, we can simply
269+ // skip the transformation and use the original RooFit parameter without
270+ // the suffix.
271+ //
272+ // A concrete example: take the following RooFit pdf in the factory language:
273+ //
274+ // "Exponential::exponential_1(x[0, 10], c[-0.1])"
275+ //
276+ // It defines en exponential exp(c * x). However, in HS3 the exponential
277+ // is defined as exp(-c * x), to RooFit would export these dictionaries
278+ // to the JSON:
279+ //
280+ // {
281+ // "name": "exponential_1", // HS3 exponential_dist with transformed parameter
282+ // "type": "exponential_dist",
283+ // "x": "x",
284+ // "c": "c_exponential_inverted"
285+ // },
286+ // {
287+ // "name": "c_exponential_inverted", // transformation function created on-the-fly on export
288+ // "type": "generic_function",
289+ // "expression": "-c"
290+ // }
291+ //
292+ // On import, we can directly take the non-transformed parameter, which is
293+ // we check for the suffix and optionally remove it from the requested
294+ // name next:
295+
296+ const std::string constParamName = p[" c" ].val ();
297+ const bool isInverted = endsWith (constParamName, " _exponential_inverted" );
298+ const std::string suffixToRemove = isInverted ? " _exponential_inverted" : " " ;
299+ RooAbsReal *c = tool->request <RooAbsReal>(removeSuffix (constParamName, suffixToRemove), name);
300+
301+ tool->wsEmplace <RooExponential>(name, *x, *c, !isInverted);
302+
261303 return true ;
262304 }
263305};
@@ -562,12 +604,12 @@ class RooLogNormalStreamer : public RooFit::JSONIO::Exporter {
562604 auto &m0 = pdf->getMedian ();
563605 auto &k = pdf->getShapeK ();
564606
565- if (pdf->useStandardParametrization ()) {
607+ if (pdf->useStandardParametrization ()) {
566608 elem[" mu" ] << m0.GetName ();
567609 elem[" sigma" ] << k.GetName ();
568610 } else {
569- elem[" mu" ] << tool->exportTransformed (&m0, " lognormal " , " log " , " log(%s)" );
570- elem[" sigma" ] << tool->exportTransformed (&k, " lognormal " , " log " , " log(%s)" );
611+ elem[" mu" ] << tool->exportTransformed (&m0, " _lognormal_log " , " log(%s)" );
612+ elem[" sigma" ] << tool->exportTransformed (&k, " _lognormal_log " , " log(%s)" );
571613 }
572614
573615 return true ;
@@ -586,7 +628,7 @@ class RooExponentialStreamer : public RooFit::JSONIO::Exporter {
586628 if (pdf->negateCoefficient ()) {
587629 elem[" c" ] << c.GetName ();
588630 } else {
589- elem[" c" ] << tool->exportTransformed (&c, " exponential " , " inverted " , " -%s" );
631+ elem[" c" ] << tool->exportTransformed (&c, " _exponential_inverted " , " -%s" );
590632 }
591633
592634 return true ;
0 commit comments