diff --git a/Slides/presentation_helper.py b/Slides/presentation_helper.py
index d63970f..81e3cd6 100644
--- a/Slides/presentation_helper.py
+++ b/Slides/presentation_helper.py
@@ -1,311 +1,311 @@
#!/usr/bin/env pyton
################################################################
from sympy import *
import base64
import sympy
import PyPDF2
import io
import IPython
from IPython.display import display
from IPython.display import HTML
import os
import fnmatch
import shutil
import subprocess
import matplotlib.pyplot as plt
import matplotlib.figure
from IPython.core.interactiveshell import InteractiveShell
from wand.image import Image as WImage
from wand.color import Color
from io import BytesIO
from tempfile import NamedTemporaryFile
from tempfile import mkdtemp
################################################################
def findImageFile(filename):
if os.path.isfile(filename):
return filename
tool_dir = os.path.dirname(__file__)
image_dir = os.path.join(tool_dir, '..', 'images')
pattern = os.path.basename(filename)
found = []
for root, dirnames, filenames in os.walk(image_dir):
for filename in fnmatch.filter(filenames, pattern):
found.append(os.path.join(root, filename))
if len(found) == 0:
raise Exception("file not found: {0}".format(filename))
if len(found) == 1:
return found[0]
raise Exception("Several files were found:\n{0}".format(found))
################################################################
def _print_latex_png(o):
o = o._repr_latex_()
dvioptions = None
exprbuffer = BytesIO()
# from IPython.core.debugger import Tracer
# Tracer()()
preview(o, output='png', viewer='BytesIO',
outputbuffer=exprbuffer, packages=('xcolor',),
dvioptions=dvioptions)
return exprbuffer.getvalue()
################################################################
def registerFormatter(_type, _format, formatter_functor):
f = InteractiveShell.instance().display_formatter.formatters[_format]
f.for_type(_type, func=formatter_functor)
################################################################
def init_printing():
sympy.init_printing()
registerFormatter(IPython.core.display.Math, 'image/png', _print_latex_png)
# f = InteractiveShell.instance().display_formatter.formatters['image/png']
# f.for_type(IPython.core.display.Math, func=_print_latex_png)
################################################################
VIDEO_TAG = """"""
def anim_to_html(anim):
if not hasattr(anim, '_encoded_video'):
with NamedTemporaryFile(suffix='.mp4') as f:
anim.save(f.name, fps=1./(anim._interval*1e-3),
extra_args=['-vcodec', 'libx264',
'-pix_fmt', 'yuv420p'])
video = open(f.name, "rb").read()
toto = base64.b64encode(video).decode()
# print anim._encoded_video
return VIDEO_TAG.format(toto)
################################################################
def display_animation(anim):
plt.close(anim._fig)
return HTML(anim_to_html(anim))
################################################################
def display_images(objs, display_flag=True, **kwargs):
htmls = [display_image(o, display_flag=False, **kwargs)
for o in objs]
width = 100/len(htmls)
htmls_withdiv = ["" for h in htmls]
for i, h in enumerate(htmls):
htmls_withdiv[i] = '
{0}
'.format(h)
html = '\n'.join(htmls_withdiv)
html = '' + html + '
'
if display_flag:
display(HTML(html))
return html
def display_image(obj, resolution=150, width=None, height=None,
display_flag=True):
if type(obj) == matplotlib.figure.Figure:
png = InteractiveShell.instance().display_formatter.format(obj)
elif type(obj) == str:
try:
fname = findImageFile(obj)
except Exception as e:
return str(e)
img = WImage(filename=fname, resolution=resolution)
img.trim()
with Color('#FDFDFD') as white:
twenty_percent = int(65535 * 0.2)
img.transparent_color(white, alpha=0.0, fuzz=twenty_percent)
if (width is None) and (height is None):
display(img)
return img
png = InteractiveShell.instance().display_formatter.format(img)
else:
raise Exception('unknown obj type for an image')
size_tag = ""
if width is not None:
size_tag += 'width="{0}"'.format(width)
if height is not None:
size_tag += 'height="{0}"'.format(height)
data = png[0]['image/png']
data = base64.b64encode(data).decode('utf-8')
html = r''
# print(html)
if display_flag:
display(HTML(html))
return html
################################################################
def display_graph(obj, **kwargs):
if not isinstance(obj, str):
raise RuntimeError(
'Graphs should be passed as a str object storing the graph'
' in dot format')
with NamedTemporaryFile(suffix='.svg') as f:
p = subprocess.Popen('dot -Tsvg -o' + f.name, shell=True,
stdin=subprocess.PIPE)
p.communicate(input=obj.encode())
display_image(f.name, **kwargs)
################################################################
def makeAnimationFromImageFiles(filenames, framerate):
temp_dir = mkdtemp()
ext = None
for idx, f in enumerate(filenames):
_dir = os.path.dirname(f)
base = os.path.basename(f)
base, _ext = os.path.splitext(base)
ext = _ext
if ext == '.pdf':
_png = os.path.join(_dir, base+".png")
subprocess.call('convert {0} {1}'.format(f, _png), shell=True)
ext = ".png"
f = _png
new_name = "file{0:05d}{1}".format(idx, ext)
new_name = os.path.join(temp_dir, new_name)
# print base, ext
# print new_name
# print "copy {0} to {1}".format(f,new_name)
shutil.copyfile(f, new_name)
pattern = os.path.join(temp_dir, 'file%05d'+ext)
with NamedTemporaryFile(suffix='.mp4') as f:
cmd = ('ffmpeg -y -framerate {2} -i {0} -vf "scale=trunc(iw/2)*2:'
'trunc(ih/2)*2" -c:v libx264 -r 30 '
'-pix_fmt yuv420p {1}').format(pattern, f.name, framerate)
# print cmd
subprocess.call(cmd, shell=True)
video = open(f.name, "rb").read()
- toto = video.encode("base64")
+ toto = base64.b64encode(video).decode()
shutil.rmtree(temp_dir)
return HTML(VIDEO_TAG.format(toto))
################################################################
def displayClassDiagram(classes, resolution=150,
width=None, height=None):
png = makeClassDiagramImage(classes, resolution,
width, height)
img = WImage(filename=png, resolution=resolution)
with Color('#FDFDFD') as white:
twenty_percent = int(65535 * 0.2)
img.transparent_color(white, alpha=0.0, fuzz=twenty_percent)
png = InteractiveShell.instance().display_formatter.format(img)
size_tag = ""
if width is not None:
size_tag += 'width="{0}"'.format(width)
if height is not None:
size_tag += 'height="{0}"'.format(height)
data = png[0]['image/png']
html = (r''.format(
base64.b64encode(data).decode('utf8'), size_tag))
display(HTML(html))
return html
################################################################
def makeClassDiagramImage(classes, resolution=150,
width=None, height=None):
with NamedTemporaryFile(suffix='.classes', delete=False) as f:
f.write(classes.encode('utf-8'))
f.flush()
fout = os.path.splitext(f.name)[0] + '.svg'
_command = ('class_dumper_dot.py --collaboration_no '
'-c {0} -o {1} -f svg'.format(f.name, fout))
# print(_command)
ret = subprocess.call(_command, shell=True)
if ret:
raise RuntimeError('could not launch commad:', _command)
return fout
################################################################
def pdf_page_to_png(src_filename, pagenums=None, resolution=72):
"""
Returns specified PDF page as wand.image.Image png.
:param PyPDF2.PdfFileReader src_pdf: PDF from which to take pages.
:param int pagenum: Page number to take.
:param int resolution: Resolution for resulting png in DPI.
"""
src_pdf = PyPDF2.PdfFileReader(file(src_filename, "rb"))
# print dir(src_pdf)
# print src_pdf.numPages
if pagenums is None:
pagenums = [0]
res = []
for n in pagenums:
dst_pdf = PyPDF2.PdfFileWriter()
dst_pdf.addPage(src_pdf.getPage(n))
pdf_bytes = io.BytesIO()
dst_pdf.write(pdf_bytes)
pdf_bytes.seek(0)
img = WImage(file=pdf_bytes, resolution=resolution)
img.convert("png")
res.append(img)
return res
################################################################
init_printing()
diff --git a/Slides/snippet_helper.py b/Slides/snippet_helper.py
index b6680b8..534cda4 100644
--- a/Slides/snippet_helper.py
+++ b/Slides/snippet_helper.py
@@ -1,491 +1,501 @@
#!/usr/bin/env python3
import subprocess
import os
import re
import abc
from pygments import highlight
from pygments.lexers import CppLexer
from pygments.lexers import PythonLexer
from pygments.lexers import MatlabLexer
from pygments.formatters import HtmlFormatter
from pygments.formatters import LatexFormatter
from pygments import token
from IPython.display import HTML
from tempfile import NamedTemporaryFile
################################################################
class SlicedSnippet(object):
"""
When you slice a snippet, this object is returned
so that all your operations can apply directly to the snippet if need be.
"""
def __init__(self, snippet, slice):
self.start = slice.start
if slice.start is None:
self.start = 1
self.end = slice.stop-1
self.snippet = snippet
def pigment(self, **kwargs):
kwargs['start'] = self.start
kwargs['end'] = self.end
return self.snippet.pigment(**kwargs)
+ def extract(self):
+ return self.snippet.extract(start=self.start, end=self.end)
+
class Snippet(abc.ABC):
"""
Snippet objects manipulate codes.
"""
default_output = 'html'
default_line_numbering = False
def __getitem__(self, slice):
return SlicedSnippet(self, slice)
def __init__(self, inp, format_flag=False,
compile_flag=False,
working_dir='/tmp'):
self.working_dir = working_dir
try:
self.loadfile(inp)
except Exception:
self.content = inp.strip()
if format_flag:
self.format()
if compile_flag:
self.compile()
# elif language == 'matlab':
# self.lexer = MatlabLexer()
def save(self, filename):
"""
Saves the snippet in another file
:param filename: The filename to save the snippet to
"""
f = open(filename, 'w')
f.write(self.content)
f.close()
def loadfile(self, inp):
filename = inp
full_filename = os.path.realpath(filename)
f = open(full_filename)
self.content = f.read()
f.close()
def getTemporaryFile(self, **kwargs):
f = NamedTemporaryFile(dir=self.working_dir, **kwargs)
f.write(self.content.encode())
f.flush()
return f
@abc.abstractmethod
def format(self):
raise RuntimeError('pure virtual routine')
@abc.abstractmethod
def execute(self, working_dir='/tmp', args='', libraries=''):
raise RuntimeError('pure virtual routine')
def compile(self, working_dir='/tmp'):
raise RuntimeError('pure virtual routine')
def get_lines(self):
return self.content.split('\n')
def get_content(self):
return self.content
def __str__(self):
_content = self.content.split('\n')
ret = ""
for i, line in enumerate(_content):
ret += '{0}: {1}\n'.format(i, line)
return ret
class KeywordLexer(object):
def __init__(self, keyword):
if keyword == 'curly_brackets':
keyword = '{|}'
self.keyword = keyword
def get_tokens(self, text):
pattern = '(' + self.keyword + ')'
splits = re.split(pattern, text)
if len(splits) == 1:
return [(token.Text, text)]
res = []
# print(splits)
# print(token.Keyword.Type)
for count, s in enumerate(splits):
# print(count, s)
if count % 2 == 0:
res.append((token.Text, s))
else:
res.append((token.Keyword.Type, s))
# print(res)
return res
class LineLexer(object):
def __init__(self, line_number):
self.line_number = line_number
def get_tokens(self, text):
splits = text.split('\n')
res = []
splits1 = '\n'.join(splits[:self.line_number]) + '\n'
splits2 = splits[self.line_number] + '\n'
splits3 = '\n' + '\n'.join(splits[self.line_number + 1:]) + '\n'
splits = [splits1] + [splits2] + [splits3]
# print(splits)
for count, s in enumerate(splits):
if count == 1:
res.append((token.Keyword.Type, s))
else:
res.append((token.Text, s))
# print(res)
return res
class CustomLatexFormatter(LatexFormatter):
def __init__(self, **kwargs):
LatexFormatter.__init__(self, **kwargs)
def format(self, tokens, outfile):
res = []
for t, s in tokens:
if t == token.Keyword.Type:
import pygments.formatters.latex as la
s = la.escape_tex(s, self.commandprefix)
s = r'\color{red}{\huge{' + s + '}}'
t = token.Escape
res.append((t, s))
LatexFormatter.format(self, res, outfile)
class CustomHtmlFormatter(HtmlFormatter):
def __init__(self, **kwargs):
HtmlFormatter.__init__(self, **kwargs)
def format(self, tokens, outfile_final):
# HtmlFormatter.format(self, tokens, outfile_final)
# return
from io import StringIO
outfile = StringIO()
res = []
ss = []
for t, s in tokens:
if t == token.Keyword.Type:
ss.append(s)
s = 'A' * 24
t = token.Text
res.append((t, s))
# print(res)
HtmlFormatter.format(self, res, outfile)
final = outfile.getvalue()
while ss:
s = ss.pop(0)
final = final.replace(
'A' * 24,
'{0}'.format(
s),
1)
outfile_final.write(final)
- def pigment(self,
- keyword=None, line_highlight=None,
- start=None, end=None,
- output=None, line_numbering=None):
-
+ def extract(self, start=None, end=None):
_content = self.content.split('\n')
_content = [(c + '\n') for c in _content]
if start is None:
start = 1
if end is None:
end = len(_content)
+ snip = _content[start - 1:end]
+ snip = ''.join(snip)
+ return snip
+
+ def pigment(self, start=None, end=None,
+ keyword=None, line_highlight=None,
+ output=None, line_numbering=None, **kwargs):
+
+ if start is None:
+ start = 1
if output is None:
output = self.default_output
lexer = self.lexer
if keyword is not None:
lexer = self.KeywordLexer(keyword)
elif line_highlight is not None:
if line_highlight < start or line_highlight > end:
raise RuntimeError('line_highlight out of the sub snippet')
line_highlight -= start
lexer = self.LineLexer(line_highlight)
if line_numbering is None:
line_numbering = self.default_line_numbering
if output == 'html':
formatter = HtmlFormatter(
full=False, linenos=line_numbering, linenostart=start)
elif output == 'latex':
formatter = LatexFormatter(
full=False, linenos=line_numbering, linenostart=start)
if (keyword is not None) or (line_highlight is not None):
format_class = self.CustomHtmlFormatter
if output == 'latex':
format_class = self.CustomLatexFormatter
formatter = format_class(
full=False, linenos=line_numbering,
linenostart=start)
- snip = _content[start - 1:end]
- snip = ''.join(snip)
+ snip = self.extract(start=start, end=end)
colored_snippet = highlight(snip, lexer, formatter)
# print(colored_snippet)
if output == 'html':
HTML_TEMPLATE = """
{}
"""
css = formatter.get_style_defs()
colored_snippet = HTML(HTML_TEMPLATE.format(css, colored_snippet))
return colored_snippet
@staticmethod
def getLatexStyleDefs():
return LatexFormatter(full=True).get_style_defs()
################################################################
class CPPSnippet(Snippet):
"""
Snippet objects manipulate Cpp codes.
At construction it can be formatted using clang-format
and it can be compiled to check for consistency.
"""
class CompilationError(Exception):
""" Compilation error """
pass
def __init__(self, inp, include_paths=None, **kwargs):
if include_paths is None:
self.include_paths = []
else:
self.include_paths = [
os.path.abspath(i) for i in include_paths]
Snippet.__init__(self, inp, **kwargs)
self.lexer = CppLexer()
def format(self):
f = self.getTemporaryFile()
p = subprocess.Popen(
'clang-format {0}'.format(f.name),
shell=True, stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode:
raise RuntimeError('Failed to launch clang-format')
formatted_file = stdout
self.content = formatted_file.decode('utf-8')
def execute(self, working_dir='/tmp', args='', libraries=''):
self.compile(working_dir=working_dir)
f = self.getTemporaryFile(suffix='.cpp', delete=False)
working_dir = os.path.dirname(f.name)
# file_dir = os.path.dirname(self.full_filename)
previous_dir = os.getcwd()
os.chdir(working_dir)
include_paths = self.include_paths + [working_dir]
include_paths = ['-I {0}'.format(a) for a in include_paths]
include_paths = ' '.join(include_paths)
p = subprocess.Popen(
'g++ -Wall -Wextra {1} {2} -o exec {0}'.format(
f.name, include_paths, libraries),
shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
ret = p.returncode
if ret != 0:
return ret, stdout, stderr
p = subprocess.Popen(
'./exec {0}'.format(args), shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
ret = p.returncode
os.chdir(previous_dir)
return ret, stdout, stderr
def compile(self):
f = self.getTemporaryFile(suffix='.cpp', delete=False)
working_dir = os.path.dirname(f.name)
# file_dir = os.path.dirname(self.full_filename)
previous_dir = os.getcwd()
os.chdir(self.working_dir)
include_paths = self.include_paths + [working_dir]
include_paths = ['-I {0}'.format(a) for a in include_paths]
include_paths = ' '.join(include_paths)
cmd = 'g++ -Wall -Wextra {1} -c {0}'.format(f.name, include_paths)
p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
ret = p.returncode
os.chdir(previous_dir)
if ret != 0:
raise CPPSnippet.CompilationError('compilation failed\n' +
cmd + '\n' +
stderr.decode('utf-8'))
os.remove(f.name)
o_file = os.path.splitext(f.name)[0] + '.o'
os.remove(o_file)
################################################################
class PythonSnippet(Snippet):
"""
Snippet objects manipulate Python codes.
At construction it can be formatted using autopep8.
"""
def __init__(self, inp, **kwargs):
Snippet.__init__(self, inp, **kwargs)
self.lexer = PythonLexer()
def format(self):
f = self.getTemporaryFile()
p = subprocess.Popen(
'autopep8 {0}'.format(f.name),
shell=True, stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode:
raise RuntimeError('Failed to launch autopep8')
formatted_file = stdout
self.content = formatted_file.decode('utf-8')
def execute(self, args=[]):
f = self.getTemporaryFile(suffix='.py')
cmd = 'python3 {0} {1}'.format(f.name, ' '.join(args))
previous_dir = os.getcwd()
os.chdir(self.working_dir)
p = subprocess.Popen(
- cmd, shell=True, stdout=subprocess.PIPE)
+ cmd, shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
os.chdir(previous_dir)
if p.returncode:
raise RuntimeError('Failed to run snippet\n' +
cmd + '\n' + stderr.decode())
return stdout
################################################################
class SnippetCollection(Snippet):
def __init__(self):
self.functions = dict()
self.func_names = []
def addFunction(self, f_name, code):
if f_name in self.functions:
raise RuntimeError('function already declared')
self.func_names.append(f_name)
self.functions[f_name] = Snippet(code, format_flag=True)
self.compile()
def __getitem__(self, key):
return self.functions[key]
def flatten(self):
global_input = """
#include
#include
#include
#include
""" + '/' * 70 + '\n\n'
for f_name in self.func_names:
global_input += "void {0}(){{\n".format(f_name)
global_input += self.functions[f_name].content
global_input += '\n}\n\n' + '/' * 70 + '\n\n'
global_input += """
int main(int argc, char ** argv){\n"""
for f_name in self.func_names:
global_input += f_name + '();\n'
global_input += '\n}\n'
flat = Snippet(global_input,
format_flag=True)
return flat
def compile(self, **kwargs):
global_snippet = self.flatten()
global_snippet.compile(**kwargs)
def save(self, filename):
global_snippet = self.flatten()
open(filename, 'w').write(global_snippet.content)
def pigment(self, *args):
return self.flatten().pigment(*args)
def last(self):
return self.functions[self.func_names[-1]]
################################################################
# def printMatlab(code):
#
# html_snippet = highlight(
# code, MatlabLexer(),
# HtmlFormatter(full=True, style='colorful',
# classprefix='matlab_'))
#
# display(HTML(html_snippet))
# # return html_snippet
# ## testing
# Snippet.default_output = 'latex'
# Snippet.default_line_numbering = True
#
# snippet = SnippetCollection()
# snippet.addFunction('if_syntax', '''
# int p, q;
# if (p > q) {
# /*
# Statement1;
# Statement2;
# */
# }
# ''')
#
# print (snippet['if_syntax'].pigment())