Initial commit.

This commit is contained in:
Mikaël Capelle 2017-05-16 11:00:50 +02:00
commit c489ce7d1e
16 changed files with 425 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*~
**/__pycache__

10
pyltk/__init__.py Normal file
View File

@ -0,0 +1,10 @@
# -*- encoding: utf-8 -*-
# flake8: noqa
from .figure import figure
from .formatter import formatter
from .makebox import makebox
from .resizebox import resizebox
from .subfloat import subfloat
from .tabular import tabular

34
pyltk/figure.py Normal file
View File

@ -0,0 +1,34 @@
# -*- encoding: utf-8 -*-
from .formatter import formatter
class figure:
""" Class representing a latex figure. """
fmt = formatter({
'content': """\\begin{{figure}}[{options}]
{centered}
{inner}
\\end{{figure}}"""
})
def __init__(self, inner, options='!h', centered=True):
""" Create a figure with given options.
Parameters:
- options Options for the figure.
- centered Set to true to add a centering command.
"""
self.inner = inner
self.options = options
self.centered = ''
if centered:
self.centered = '\\centering'
def __str__(self):
return self.fmt.format('content', {
'options': self.options,
'centered': self.centered,
'inner': self.inner
})

13
pyltk/formatter.py Normal file
View File

@ -0,0 +1,13 @@
# -*- encoding: utf-8 -*-
class formatter:
""" Simple formatter class. """
def __init__(self, templates):
self.templates = templates
def format(self, key, data):
""" Format the internal state. """
return self.templates[key].format(**data)

41
pyltk/makebox.py Normal file
View File

@ -0,0 +1,41 @@
# -*- encoding: utf-8 -*-
from .formatter import formatter
class makebox:
""" Class representing an unindented makebox. """
fmt = formatter({
'content': """{noindent}\\makebox[{width}]{{
{inner}
}}"""
})
def __init__(self, inner, width=None, noindent=True):
""" Create a new makebox with given width.
Parameters:
- width Width of the box (string, float, or None). If float,
represent a percentage of \\textwidth. None is used to have
\\textwidth.
- noindent Add a \\noindent command before the box.
"""
self.inner = inner
self.width = width
if self.width is None:
self.width = '\\textwidth'
elif type(self.width) != 'str':
self.width = '{}\\textwidth'.format(self.width)
self.noindent = ''
if self.noindent:
self.noindent = '\\noindent'
def __str__(self):
return self.fmt.format('content', {
'inner': self.inner,
'width': self.width,
'noindent': self.noindent
})

38
pyltk/resizebox.py Normal file
View File

@ -0,0 +1,38 @@
# -*- encoding: utf-8 -*-
from .formatter import formatter
class resizebox:
""" Class representing a latex resizebox. """
fmt = formatter({
'content': """\\resizebox{{{width}}}{{{height}}}{{
{inner}
}}"""
})
def __init__(self, inner, width, height="!"):
""" Create a resizebox with given width and height.
Parameters:
- width Width of the box.
- height Height of the box.
The width / height parameters work differently depending on their
types:
- str Use as it is (e.g. "0.5\\linewidth", "!").
- others Use as a percentage of linewidth (e.g. 0.5).
"""
self.inner = inner
self.width = width
if type(width) != 'str':
self.width = '{}\\linewidth'.format(width)
self.height = height
def __str__(self):
return self.fmt.format('content', {
'width': self.width,
'height': self.height,
'inner': self.inner
})

23
pyltk/subfloat.py Normal file
View File

@ -0,0 +1,23 @@
# -*- encoding: utf-8 -*-
from .formatter import formatter
class subfloat:
""" Class representing a latex subfloat. """
fmt = formatter({
'content': """\\subfloat[{caption}]{{
{inner}
}}"""
})
def __init__(self, inner, caption):
self.caption = caption
self.inner = inner
def __str__(self):
return self.fmt.format('content', {
'caption': self.caption,
'inner': self.inner
})

53
pyltk/tabular.py Normal file
View File

@ -0,0 +1,53 @@
# -*- encoding: utf-8 -*-
from .formatter import formatter
class tabular:
""" Class representing a latex tabular. """
fmt = formatter({
'content': """\\begin{{tabular}}{{{columns}}}
{inner}
\\end{{tabular}}"""
})
def __init__(self, rows, columns=None):
""" Create a tabular with given rows and column specification.
Parameters:
- rows Rows for the tabular (list of list or list of string).
- columns String representing columns.
If `rows` is a str, an empty tabular is created and `rows` is used
instead of `columns` for the columns specification.
"""
if type(rows) == str:
columns = rows
rows = []
self.columns = columns
self.rows = []
for row in rows:
self.addrow(row)
def addrow(self, row):
""" Add a row to the tabular.
Parameters:
- row Array or string (array will be joined with ' & ').
"""
if type(row) != 'str':
row = ' & '.join(map(str, row))
self.rows.append(row)
def addrows(self, rows):
""" Add multiple rows to the tabular (see addrow). """
for row in rows:
self.addrow(row)
def __str__(self):
inner = '\\\\\n'.join(self.rows)
return self.fmt.format('content', {
'columns': self.columns,
'inner': inner
})

6
pyltk/tikz/__init__.py Normal file
View File

@ -0,0 +1,6 @@
# -*- encoding: utf-8 -*-
# flake8: noqa
from .plots import *
from .tikzpicture import tikzpicture

45
pyltk/tikz/axis.py Normal file
View File

@ -0,0 +1,45 @@
# -*- encoding: utf-8 -*-
from ..formatter import formatter
class axis:
""" Class representing an axis. """
fmt = formatter({
'options': '[{content}]',
'legends': '\\legend{{{content}}}',
'content': """\\begin{{axis}}{options}
{inner}
{legend}
\\end{{axis}}"""
})
def __init__(self, *args, **kargs):
self.options = kargs
self.plots = []
for arg in args:
self.addplot(arg)
def addplot(self, pl):
self.plots.append(pl)
def format_options(self, options):
if not options:
return ''
opts = []
for k, v in options.items():
opts.append('{key} = {{{value}}}'.format(key=k, value=v))
return self.fmt.format('options', {
'content': ', '.join(opts)
})
def __str__(self):
return self.fmt.format('content', {
'options': self.format_options(self.options),
'inner': '\n'.join(map(str, self.plots)),
'legend': self.fmt.format('legends', {
'content': ', '.join('{{{}}}'.format(p.legend)
for p in self.plots)
})
})

View File

@ -0,0 +1,15 @@
# -*- encoding: utf-8 -*-
from .generic_plot import generic_plot
class coordinates_plot(generic_plot):
def __init__(self, *args, **kargs):
super().__init__(*args, **kargs)
def format_data(self, data):
pts = []
for d in data:
pts.append('({}, {})'.format(*d))
return 'coordinates {{{}}}'.format(''.join(pts))

View File

@ -0,0 +1,24 @@
# -*- encoding: utf-8 -*-
from .generic_plot import generic_plot
class errorbars_plot(generic_plot):
def __init__(self, legend, data, options=[]):
options = options + [
'error bars/.cd', ('y dir', 'both'), ('y explicit')]
super().__init__(legend, data, options)
def format_data(self, data):
rows = []
for d in data:
x, y = d[:2]
try:
p, n = d[2]
except TypeError:
p = d[2]
n = p
rows.append('({x}, {y}) += (0, {p}) -= (0, {n})'.format(
x=x, y=y, p=p, n=n))
return 'coordinates {{{}}}'.format('\n'.join(rows))

View File

@ -0,0 +1,35 @@
# -*- encoding: utf-8 -*-
from ..formatter import formatter
class generic_plot:
""" Class representing a pgfplots plot. """
fmt = formatter({
'options': '+[{content}]',
'content': """\\addplot{options} {data};"""
})
def __init__(self, legend, data, options=[]):
self.legend = legend
self.data = data
self.options = options
def format_options(self, options):
if not options:
return ''
opts = []
for opt in options:
if type(opt) is not str:
opt = '{}={}'.format(*opt)
opts.append(str(opt))
return self.fmt.format('options', {
'content': ', '.join(opts)
})
def __str__(self):
return self.fmt.format('content', {
'data': self.format_data(self.data),
'options': self.format_options(self.options)
})

7
pyltk/tikz/plots.py Normal file
View File

@ -0,0 +1,7 @@
# -*- encoding: utf-8 -*-
# flake8: noqa
from .generic_plot import generic_plot
from .coordinates_plot import coordinates_plot
from .errorbars_plot import errorbars_plot

29
pyltk/tikz/tikzpicture.py Normal file
View File

@ -0,0 +1,29 @@
# -*- encoding: utf-8
from ..formatter import formatter
from .axis import axis
class tikzpicture:
""" Class representing a latex tikzfigure. """
fmt = formatter({
'content': """\\begin{{tikzpicture}}
{inner}
\\end{{tikzpicture}}"""
})
def __init__(self, axis=[]):
self.axis = []
def addaxis(self, *args, **kargs):
ax = args[0]
if not isinstance(ax, axis):
ax = axis(*args, **kargs)
self.axis.append(ax)
def __str__(self):
return self.fmt.format('content', {
'inner': '\n'.join(map(str, self.axis))
})

50
tests/test_basic.py Normal file
View File

@ -0,0 +1,50 @@
# -*- encoding: utf-8 -*-
import sys
sys.path += ['..']
from pyltk import subfloat, tabular, resizebox, makebox, figure
from pyltk.tikz import tikzpicture, errorbars_plot, coordinates_plot
if __name__ == "__main__":
data = [[1.00000000e+00,
4.57213083e+00],
[2.00000000e+00,
1.16046200e+01],
[ 4.00000000e+00,
2.71873880e+01],
[ 5.00000000e+00,
3.36039380e+01],
[ 1.00000000e+01,
7.21689923e+01],
[ 2.00000000e+01,
1.50422028e+02]]
tk = tikzpicture()
tk.addaxis(coordinates_plot('test', data),
xlabel='', ylabel='Computation Time [s]')
tk2 = tikzpicture()
tk2.addaxis(errorbars_plot('test 2', [
[0, 5, (2, 3)],
[1, 8, (4, 5)]
]))
tk3 = tikzpicture()
tk3.addaxis(errorbars_plot('test 2', [
[0, 5, 3],
[4, 8, 4]
]))
s1 = subfloat(tk, 'Caption 1')
s2 = subfloat(tk2, 'Caption 2')
s3 = subfloat(tk3, 'Caption 3')
s4 = subfloat('', 'Caption 4')
tab = tabular([
[resizebox(s1, 0.5), resizebox(s2, 0.5)],
[resizebox(s3, 0.5), resizebox(s4, 0.5)]
], columns='cc')
print(figure(makebox(tab), '!h'))