Home | News | Documentation | Download

Import custom PDF in RooWorkspace

Is there a way to store a custom PDF in a RooWorkspace? The documentation seems to suggest that a combination of addClassDeclImportDir, addClassImplImportDir, and importClassCode should do the trick, but it does not actually work. Ideally, I would like to store a fitted custom PDF so I can retrieve it for plotting/manipulation later.

NB:
This was raised previously in the forum here, but the only answer was

Building from source is not always an option, and it is almost never an easy option. Should I take from this that there is simply no way to store a custom PDF shape for later use?


Reproducer:

import os

import ROOT as r

r.gROOT.ProcessLine(".x RooSDSCBShape.cxx")

ws = r.RooWorkspace("ws")

ws.addClassDeclImportDir(os.getcwd())
ws.addClassImplImportDir(os.getcwd())

ws.importClassCode(r.RooSDSCBShape.Class())

Output:

[#0] ERROR:ObjectHandling -- RooWorkspace::CodeRepo(ws) ERROR: cannot retrieve code file names for class RooSDSCBShape through ROOT TClass interface, unable to import code

RooSDSCBShape.cxx (7.4 KB) RooSDSCBShape.h (1.8 KB)

I think we need @moneta for this one.

Hi,
I don’t think anything has changed compared to what stated in the previous posts. @pcanal might know more.
Probably is better creating a GitHub issue on this

Cheers
Lorenzo

It might work if you generate a dictionary for the PDF class and add a ClassImp. Or with or without a dictionary if you call

TClass::GetClass( classname_of_the_pdf )->SetDeclFileName( path_name_to_header_file );
TClass::GetClass( classname_of_the_pdf )->SetImplFileName( path_name_to_source_file );

Cheers,
Philippe.

Thanks for the response. It seems that it almost works.

  1. There is no SetDeclFileName attribute of TClass. One must use SetDeclFile.
  2. While the RooWorkspace now imports without errors, ROOT throws an error when trying to extract it after it has been saved.

Reproducer follows.


import os

import ROOT as r

r.gROOT.ProcessLine(".x RooSDSCBShape.cxx")

cls = r.TClass.GetClass("RooSDSCBShape")
cls.SetDeclFile(f"{os.getcwd()}/RooSDSCBShape.h", 0)
cls.SetImplFileName(f"{os.getcwd()}/RooSDSCBShape.cxx")

ws = r.RooWorkspace("ws")
ws.addClassDeclImportDir(os.getcwd())
ws.addClassImplImportDir(os.getcwd())
ws.importClassCode(cls)

ws.writeToFile("test.root")

So far so good. Output:

RooFit v3.60 -- Developed by Wouter Verkerke and David Kirkby 
                Copyright (C) 2000-2013 NIKHEF, University of California & Stanford University
                All rights reserved, please read http://roofit.sourceforge.net/license.txt

(RooSDSCBShape) An instance of RooSDSCBShape.
[#1] INFO:ObjectHandling -- RooWorkspace::autoImportClass(ws) importing code of class RooSDSCBShape from /<path/to>/RooSDSCBShape.cxx and /<path/to>/RooSDSCBShape.h

Now, I attempt to extract the saved workspace:

f = r.TFile.Open("test.root")
inws = f.Get("ws")

Output:

[#1] INFO:ObjectHandling -- RooWorkspace::CodeRepo::compileClasses() creating code export directory .wscode.305a6bb0-6f9d-11eb-9678-a001a8c0beef.ws to extract coded embedded in workspace
[#1] INFO:ObjectHandling -- RooWorkspace::CodeRepo::compileClasses() Extracting declaration code of class RooSDSCBShape, file .wscode.305a6bb0-6f9d-11eb-9678-a001a8c0beef.ws/RooSDSCBShape.h
[#1] INFO:ObjectHandling -- RooWorkspace::CodeRepo::compileClasses() Extracting implementation code of class RooSDSCBShape, file .wscode.305a6bb0-6f9d-11eb-9678-a001a8c0beef.ws/RooSDSCBShape.cxx
[#1] INFO:ObjectHandling -- RooWorkspace::CodeRepo::compileClasses() Compiling code unit RooSDSCBShape to define class RooSDSCBShape
Info in <TMacOSXSystem::ACLiC>: creating shared library /<path/to>/Downloads/.wscode.305a6bb0-6f9d-11eb-9678-a001a8c0beef.ws/RooSDSCBShape_cxx.so
ld: library not found for -lCheckFix
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
Error in <ACLiC>: Executing 'cd "/<path/to>/Downloads/.wscode.305a6bb0-6f9d-11eb-9678-a001a8c0beef.ws" ; x86_64-apple-darwin13.4.0-clang++ -fPIC -c -O3 -DNDEBUG -march=core2 -mtune=haswell -mssse3 -ftree-vectorize -fPIC -fPIE -fstack-protector-strong -O2 -pipe -stdlib=libc++ -fvisibility-inlines-hidden -fmessage-length=0 -I/<path/to>/opt/anaconda3/envs/aslsRun2_ana/include -fdebug-prefix-map=/Users/runner/miniforge3/conda-bld/root_1607274686894/work=/usr/local/src/conda/root_base-6.22.6 -fdebug-prefix-map=/<path/to>/opt/anaconda3/envs/aslsRun2_ana=/usr/local/src/conda-prefix -std=c++17 -Wc++11-narrowing -Wsign-compare -Wsometimes-uninitialized -Wconditional-uninitialized -Wheader-guard -Warray-bounds -Wcomment -Wtautological-compare -Wstrncat-size -Wloop-analysis -Wbool-conversion -m64 -pipe -W -Woverloaded-virtual -fsigned-char -fno-common -Qunused-arguments -pthread -stdlib=libc++  -I$ROOTSYS/include -I"/<path/to>/opt/anaconda3/envs/aslsRun2_ana/etc/" -I"/<path/to>/opt/anaconda3/envs/aslsRun2_ana/etc//cling" -I"/<path/to>/opt/anaconda3/envs/aslsRun2_ana/include/" -I"/<path/to>/opt/anaconda3/envs/aslsRun2_ana/include" -I"/<path/to>/opt/anaconda3/envs/aslsRun2_ana/include/python3.9"   -D__ACLIC__ "/<path/to>/Downloads/.wscode.305a6bb0-6f9d-11eb-9678-a001a8c0beef.ws/RooSDSCBShape_cxx_ACLiC_dict.cxx" ; x86_64-apple-darwin13.4.0-clang++ -O3 -DNDEBUG "/<path/to>/Downloads/.wscode.305a6bb0-6f9d-11eb-9678-a001a8c0beef.ws/RooSDSCBShape_cxx_ACLiC_dict.o" -dynamiclib -Wl,-headerpad_max_install_names -m64 -single_module -Wl,-dead_strip_dylibs -undefined dynamic_lookup   "-lfakelink" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libz.1.2.11.dylib" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/liblzma.5.dylib" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libcrypto.1.1.dylib" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libsqlite3.0.dylib" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libssl.1.1.dylib" "-lnetwork" "-lpcap.A" "-ldns_services" "-lz.1" "-lcoretls_cfhelpers" "-lapple_nghttp2" "-lenergytrace" "-lsqlite3" "-lMobileGestalt" "-lcoretls" "-lxar.1" "-lcompression" "-larchive.2" "-lxml2.2" "-llzma.5" "-lbz2.1.0" "-liconv.2" "-lcharset.1" "-lCheckFix" "-lmecabra" "-lmecab" "-lgermantok" "-lThaiTokenizer" "-lChineseTokenizer" "-lcmph" "-lutil" "-lapp_launch_measurement" "-lxslt.1" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libcppyy3_9.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libcppyy_backend3_9.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libCore.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libc++.1.0.dylib" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libpcre.1.dylib" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libxxhash.0.8.0.dylib" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/liblz4.1.9.2.dylib" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libzstd.1.4.5.dylib" "-lspindump" "-late" "-lexpat.1" "-lIOReport" "-lSMC" "-lmis" "-lheimdal-asn1" "-lAudioStatistics" "-lperfcheck" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libRIO.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libThread.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libCling.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libffi.7.dylib" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libROOTPythonizations3_9.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libTree.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libNet.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libImt.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libtbb.dylib" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libRooFitCore.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libMinuit.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libFoam.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libGraf.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libHist.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libMatrix.6.22.06.so" "/<path/to>/opt/anaconda3/envs/aslsRun2_ana/lib/libMathCore.6.22.06.so" "-lsandbox.1" "-lCoreStorage" "-lcsfde" "-lMatch.1" -o "/<path/to>/Downloads/.wscode.305a6bb0-6f9d-11eb-9678-a001a8c0beef.ws/RooSDSCBShape_cxx.so"' failed!
[#0] ERROR:ObjectHandling -- RooWorkspace::CodeRepo::compileClasses() ERROR compiling class RooSDSCBShape, to fix this you can do the following: 
  1) Fix extracted source code files in directory .wscode.305a6bb0-6f9d-11eb-9678-a001a8c0beef.ws/
  2) In clean ROOT session compiled fixed classes by hand using '.x .wscode.305a6bb0-6f9d-11eb-9678-a001a8c0beef.ws/ClassName.cxx+'
  3) Reopen file with RooWorkspace with broken source code in UPDATE mode. Access RooWorkspace to force loading of class
     Broken instances in workspace will _not_ be compiled, instead precompiled fixed instances will be used.
  4) Reimport fixed code in workspace using 'RooWorkspace::importClassCode("*",kTRUE)' method, Write() updated workspace to file and close file
  5) Reopen file in clean ROOT session to confirm that problems are fixed

Created GitHub issue #7249.