1 from __future__
import print_function
10 from hashlib
import sha1
11 from contextlib
import contextmanager
12 from subprocess
import check_output
13 from IPython
import get_ipython
14 from IPython.display
import HTML
15 from IPython.core.extensions
import ExtensionManager
16 import IPython.display
26 cppMIME =
'text/x-c++src'
27 ipyMIME =
'text/x-ipython'
29 _jsDefaultHighlight =
"""
30 // Set default mode for code cells
31 IPython.CodeCell.options_default.cm_config.mode = '{mimeType}';
32 // Set CodeMirror's current mode
33 var cells = IPython.notebook.get_cells();
34 cells[cells.length-1].code_mirror.setOption('mode', '{mimeType}');
35 // Set current mode for newly created cell
36 cells[cells.length-1].cm_config.mode = '{mimeType}';
39 _jsMagicHighlight =
"IPython.CodeCell.config_defaults.highlight_modes['magic_{cppMIME}'] = {{'reg':[/^%%cpp/]}};"
42 _jsNotDrawableClassesPatterns = [
"TGraph[23]D",
"TH3*",
"TGraphPolar",
"TProf*",
"TEve*",
"TF[23]",
"TGeo*",
"TPolyLine3D"]
45 _jsROOTSourceDir =
"https://root.cern.ch/js/dev/"
51 style="width: {jsCanvasWidth}px; height: {jsCanvasHeight}px">
58 'JSRootCore' : '{jsROOTSourceDir}/scripts/JSRootCore',
59 'JSRootPainter' : '{jsROOTSourceDir}/scripts/JSRootPainter',
63 require(['JSRootCore', 'JSRootPainter'],
64 function(Core, Painter) {{
65 var obj = Core.parse('{jsonContent}');
66 Painter.draw("{jsDivId}", obj, "{jsDrawOptions}");
73 _enableJSVisDebug =
False
84 global _enableJSVisDebug
86 _enableJSVisDebug =
True
90 global _enableJSVisDebug
92 _enableJSVisDebug =
False
98 '''Return appropriate file extension for a shared library
99 >>> _getLibExtension('darwin')
101 >>> _getLibExtension('win32')
103 >>> _getLibExtension('OddPlatform')
110 return pExtMap.get(thePlatform,
'.so')
113 print(
"Welcome to ROOTaaS %s" %ROOT.gROOT.GetVersion())
117 originalLevel = ROOT.gErrorIgnoreLevel
118 ROOT.gErrorIgnoreLevel = level
120 ROOT.gErrorIgnoreLevel = originalLevel
125 >>> commentRemover(s)
127 >>> s="int /** Test **/ main() {return 0;}"
128 >>> commentRemover(s)
129 'int main() {return 0;}'
131 def blotOutNonNewlines( strIn ) :
132 return "" + (
"\n" * strIn.count(
'\n'))
134 def replacer( match ) :
136 if s.startswith(
'/'):
137 return blotOutNonNewlines(s)
141 pattern = re.compile(\
142 r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
143 re.DOTALL | re.MULTILINE)
145 return re.sub(pattern, replacer, text)
151 ROOT.gInterpreter.ProcessLine(code)
155 ROOT.gInterpreter.Declare(code)
166 out = check_output(command.split())
169 sys.stderr.write(
"%s (command was %s)\n" %(errMsg,command))
174 This function is a workaround. On osx, it is impossible to link against
175 libzmq.so, among the others. The error is known and is
176 "ld: can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)"
177 We cannot at the moment force Aclic to change the linker command in order
178 to exclude these libraries, so we launch a second root session to compile
179 the library, which we then load.
181 command =
'root -l -q -b -e gSystem->CompileMacro(\"%s\",\"k\")*0'%fileName
183 libNameBase = fileName.replace(
".C",
"_C")
184 ROOT.gSystem.Load(libNameBase)
187 '''Convert code to a unique file name
189 >>> _codeToFilename("int f(i){return i*i;}")
192 fileNameBase = sha1(code).hexdigest()[0:8]
193 return fileNameBase +
".C"
196 '''Dump code to file whose name is unique
198 >>> _codeToFilename("int f(i){return i*i;}")
202 with open (fileName,
'w')
as ofile:
215 nbStreamsPyStreamsMap={sys.stderr:sys.__stderr__,sys.stdout:sys.__stdout__}
220 os.dup2(self.
pipe_in, self.pyStream.fileno())
224 flushFunctionName=
'_ROOTaaS_Flush'
225 if (
not hasattr(ROOT,flushFunctionName)):
227 self.
flush = getattr(ROOT,flushFunctionName)
230 r, _, _ = select.select([self.pipe_out], [], [], 0)
237 out += os.read(self.pipe_out, 8192)
240 self.nbStream.write(out)
244 self.shell.events.register(
'post_execute', self.
post_execute)
248 Capture the canvas which is drawn to display it.
257 for can
in ROOT.gROOT.GetListOfCanvases():
263 self.shell.events.register(
'pre_execute', self.
_pre_execute)
264 self.shell.events.register(
'post_execute', self.
_post_execute)
273 Change the mode of the notebook to CPP. It is preferred to use cell magic,
274 but this option is handy to set up servers and for debugging purposes.
277 cpptransformer.load_ipython_extension(ip)
279 IPython.display.display_javascript(_jsDefaultHighlight.format(mimeType = cppMIME), raw=
True)
280 print(
"Notebook is in Cpp mode")
284 Capture the canvas which is drawn and decide if it should be displayed using
294 Get the list of primitives in the pad, recursively descending into
295 histograms and graphs looking for fitted functions.
297 primitives = self.thePad.GetListOfPrimitives()
298 primitivesNames = map(
lambda p: p.ClassName(), primitives)
303 return sorted(primitivesNames)
307 Every DIV containing a JavaScript snippet must be unique in the
308 notebook. This methods provides a unique identifier.
310 CanvasDrawer.jsUID += 1
311 return CanvasDrawer.jsUID
315 if not _enableJSVis:
return False
317 for unsupportedPattern
in _jsNotDrawableClassesPatterns:
318 for primitiveTypeName
in primitivesTypesNames:
319 if fnmatch.fnmatch(primitiveTypeName,unsupportedPattern):
320 print(
"The canvas contains an object of a type jsROOT cannot currently handle (%s). Falling back to a static png." %primitiveTypeName, file=sys.stderr)
326 pad = ROOT.gROOT.GetListOfCanvases().FindObject(ROOT.gPad.GetName())
327 json = ROOT.TBufferJSON.ConvertToJSON(pad, 3)
331 divId =
'root_plot_' + str(self.
_getUID())
332 thisJsCode = _jsCode.format(jsCanvasWidth = _jsCanvasWidth,
333 jsCanvasHeight = _jsCanvasHeight,
334 jsROOTSourceDir = _jsROOTSourceDir,
335 jsonContent=json.Data(),
340 IPython.display.display(HTML(thisJsCode))
344 ofile = tempfile.NamedTemporaryFile(suffix=
".png")
346 self.thePad.SaveAs(ofile.name)
347 img = IPython.display.Image(filename=ofile.name, format=
'png', embed=
True)
348 IPython.display.display(img)
352 if _enableJSVisDebug:
368 Invoke the draw function and intercept the graphics
376 style.SetFuncWidth(3)
377 style.SetHistLineWidth(3)
378 style.SetMarkerStyle(8)
379 style.SetMarkerSize(.5)
380 style.SetMarkerColor(ROOT.kBlue)
384 extNames = [
"ROOTaaS.iPyROOT." + name
for name
in [
"cppmagic"]]
386 extMgr = ExtensionManager(ip)
387 for extName
in extNames:
388 extMgr.load_extension(extName)
389 cppcompleter.load_ipython_extension(ip)
391 for capture
in captures: capture.register()
395 ROOT.enableJSVis = enableJSVis
396 ROOT.disableJSVis = disableJSVis
397 ROOT.enableJSVisDebug = enableJSVisDebug
398 ROOT.disableJSVisDebug = disableJSVisDebug
399 ROOT.TCanvas.DrawCpp = ROOT.TCanvas.Draw
400 ROOT.TCanvas.Draw = _PyDraw
403 ipDispJs = IPython.display.display_javascript
405 ipDispJs(
"require(['codemirror/mode/clike/clike'], function(Clike) { console.log('ROOTaaS - C++ CodeMirror module loaded'); });", raw=
True)
407 ipDispJs(_jsMagicHighlight.format(cppMIME = cppMIME), raw=
True)
def _getLibExtension(thePlatform)
def __init__(self, thePad)
def declareCppCodeImpl(code)
def loadExtensionsAndCapturers()
def _getListOfPrimitivesNamesAndTypes(self)
def _dumpToUniqueFile(code)
def _invokeAclicMac(fileName)
def processCppCodeImpl(code)
def enableCppHighlighting()
def _setIgnoreLevel(level)
def _codeToFilename(code)