Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce decorator-style API #3

Closed
wookayin opened this issue Oct 23, 2017 · 7 comments
Closed

Introduce decorator-style API #3

wookayin opened this issue Oct 23, 2017 · 7 comments

Comments

@wookayin
Copy link
Owner

wookayin commented Oct 23, 2017

Decorators are pretty?

For example (name is undecided), we can simply define a decorated "op builder" function:

@tfplot.op(batch=True)
def plot_heatmap(heatmap, cmap='jet')
    # heatmap: a [16x16] numpy array here
    fig, ax = tfplot.subplots(figsize=(4, 3))
    im = ax.imshow(heatmap, cmap=cmap)
    fig.colorbar(im)
    return fig

# heatmap_tensor : a float32 Tensor of shape [4, 16, 16], for example
>>> plot_heatmap(heatmap_tensor)
Tensor("PlotHeatmap:0", shape=(4, ?, ?, 3), dtype=uint8)

Instead of:

# heatmap_tensor : a float32 Tensor of shape [4, 16, 16], for example
>>> PlotOp = tfplot.wrap(figure_heatmap, batch=True, name='PlotHeatmap')
>>> PlotOp(heatmap_tensor)
Tensor("PlotHeatmap:0", shape=(4, ?, ?, 3), dtype=uint8)
@ferrine
Copy link

ferrine commented Jan 12, 2018

Decorator is a cool thing, should have batch/name arguments. As I understand the implementation, the following should work as well. I think it will be a good thing to work around with first argument of wrap function and in case it is not defined, create a factory wrapper function that decorates plot_heatmap in above example

import functools
NotDefined = object()
def wrap(func=NotDefined, arg=1, **kwargs):
    if func is NotDefined:
        args = locals().copy()
        args.pop('func')
        args.pop('kwargs')
        args.update(kwargs)
        return functools.partial(wrap, **args)
    # or your code below
    def wrapped(**kwargs1):
        if arg == 1:
            print('hi')
        else:
            print('bye')
        kw = kwargs.copy()
        kw.update(kwargs1)
        return func(**kw)
    return wrapped

def fn1(a=1, b=2):
    print('a =', a)
    print('b =', b)
@wrap
def fn2(a=1, b=2):
    print('a =', a)
    print('b =', b)

@wrap(arg=2)
def fn3(a=1, b=2):
    print('a =', a)
    print('b =', b)

fn4 = wrap(fn1, arg=2, a=3)

fn1()
fn2()
fn3()
fn4()
-------------
a = 1
b = 2
hi
a = 1
b = 2
bye
a = 1
b = 2
bye
a = 3
b = 2

@ferrine
Copy link

ferrine commented Jan 13, 2018

you can use https://github.com/ferrine/biwrap, available at pypi

@wookayin
Copy link
Owner Author

wookayin commented Jan 13, 2018

Nice suggestion! I will take a look at this soon, thanks.

@wookayin
Copy link
Owner Author

I have been working on this these days, please see #7 (in progress).

  • tfplot.wrap: The existing tfplot.wrap() can be used as a decorator as well, as suggested by @ferrine.
  • tfplot.autowrap: Similar to wrap, but supports automatic injection of fig, ax. This will replace wrap_axesplot soon. Batch supports, etc. will be added soon.

/cc @ferrine Do you want to take a look or review it?

@wookayin
Copy link
Owner Author

I believe this API is good enough, will be released as v0.3.

https://github.com/wookayin/tensorflow-plot/blob/master/examples/showcases.ipynb

@ferrine
Copy link

ferrine commented Feb 15, 2019

Oh, I was missiing notifications for a long time, is review still needed?

@wookayin
Copy link
Owner Author

If you want to kindly give some suggestions, it would be greatly appreciated of course.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants