Skip to content

Commit

Permalink
Pipeline enhancements (#222)
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Jan 28, 2019
1 parent fc5fe3f commit 07703ee
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 7 deletions.
18 changes: 13 additions & 5 deletions examples/user_guide/Pipelines.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
"* ``param.output(param.Number)``: Declaring an output with a specific ``Parameter`` or Python type also declares an output with the name of the method but declares that the output will be of a specific type.\n",
"* ``param.output(c=param.Number)``: Declaring an output using a keyword argument allows overriding the method name as the name of the output and declares the type.\n",
"\n",
"It is also possible to declare multiple parameters, either as keywords (Python >= 3.6 required) or tuples:\n",
"\n",
"* ``param.output(c=param.Number, d=param.String)`` or ``param.output(('c', param.Number), ('d', param.String))``\n",
"\n",
"In the example below the output is simply the result of multiplying the two inputs (``a`` and ``b``) which will produce output ``c``. Additionally we declare a ``view`` method which returns a ``LaTeX`` pane which will render the equation to ``LaTeX``. Finally a ``panel`` method declares returns a ``panel`` object rendering both the parameters and the view; this is the second convention that a ``Pipeline`` expects.\n",
"\n",
"Let's start by displaying this stage on its own:"
Expand All @@ -60,13 +64,15 @@
"\n",
" b = param.Number(default=5, bounds=(0, 10))\n",
" \n",
" @param.output(c=param.Number)\n",
" @param.output(c=param.Number, d=param.Number)\n",
" def output(self):\n",
" return self.a * self.b\n",
" return self.a * self.b, self.a ** self.b\n",
" \n",
" @param.depends('a', 'b')\n",
" def view(self):\n",
" return pn.pane.LaTeX('$%s * %s = %s$' % (self.a, self.b, self.output()))\n",
" c, d = self.output()\n",
" return pn.pane.LaTeX('${a} * {b} = {c}$\\n${a}^{{{b}}} = {d}$'.format(\n",
" a=self.a, b=self.b, c=c, d=d))\n",
"\n",
" def panel(self):\n",
" return pn.Row(self.param, self.view)\n",
Expand Down Expand Up @@ -117,7 +123,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"A ``Pipeline`` with only a single stage is not much of a ``Pipeline`` of course, so it's time to set up a second stage, which consumes the outputs of the first. Recall that ``Stage1`` declares one output named ``c``, this means that if the output from ``Stage1`` should flow to ``Stage2``, the latter should declare a ``Parameter`` named ``c`` which will consume the output of the first stage. Below we therefore define parameters ``c`` and ``exp`` and since ``c`` is the output of the first stage the ``c`` parameter will be declared with a negative precedence stopping ``panel`` from generating a widget for it. Otherwise this class is very similar to the first one, it declares both a ``view`` method which depends on the parameters of the class and a ``panel`` method which returns a view of the object."
"A ``Pipeline`` with only a single stage is not much of a ``Pipeline`` of course, so it's time to set up a second stage, which consumes the outputs of the first. Recall that ``Stage1`` declares one output named ``c``, this means that if the output from ``Stage1`` should flow to ``Stage2``, the latter should declare a ``Parameter`` named ``c`` which will consume the output of the first stage. It does not have to consume all parameters so we can ignore output ``d``.\n",
"\n",
"Below we therefore define parameters ``c`` and ``exp`` and since ``c`` is the output of the first stage the ``c`` parameter will be declared with a negative precedence stopping ``panel`` from generating a widget for it. Otherwise this class is very similar to the first one, it declares both a ``view`` method which depends on the parameters of the class and a ``panel`` method which returns a view of the object."
]
},
{
Expand All @@ -139,7 +147,7 @@
" def panel(self):\n",
" return pn.Row(self.param, self.view)\n",
" \n",
"stage2 = Stage2(c=stage1.output())\n",
"stage2 = Stage2(c=stage1.output()[0])\n",
"stage2.panel()"
]
},
Expand Down
25 changes: 23 additions & 2 deletions panel/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(self, stages=[], **params):
self._progress_sel.add_subscriber(self._set_stage)
prev_button = Param(self.param, parameters=['previous'], show_name=False)
next_button = Param(self.param, parameters=['next'], show_name=False)
prev_button.layout[0][0].disabled = True
self._progress_bar = Row(self._make_progress, prev_button, next_button)
spinner = Pane(os.path.join(os.path.dirname(__file__), 'assets', 'spinner.gif'))
self._spinner_layout = Row(Spacer(width=300), Column(Spacer(height=200), spinner))
Expand Down Expand Up @@ -121,10 +122,27 @@ def _set_stage(self, index):
steps = idx-self._stage
if steps < 0:
for i in range(abs(steps)):
self._previous()
e = self._previous()
if e:
break
else:
for i in range(steps):
self._next()
e = self._next()
if e:
break

def _update_button(self):
# Disable previous button
if self._stage == 0:
self._progress_bar[1].layout[0][0].disabled = True
else:
self._progress_bar[1].layout[0][0].disabled = False

# Disable next button
if self._stage == len(self._stages)-1:
self._progress_bar[2].layout[0][0].disabled = True
else:
self._progress_bar[2].layout[0][0].disabled = False

@param.depends('next', watch=True)
def _next(self):
Expand All @@ -134,13 +152,15 @@ def _next(self):
try:
new_stage = self._init_stage()
self._layout[2][0] = new_stage
self._update_button()
except Exception as e:
self._stage -= 1
self._error.object = ('Next stage raised following error:\n\n\t%s: %s'
% (type(e).__name__, str(e)))
self._layout[2][0] = prev_state
if self.debug:
raise e
return e
else:
self._error.object = ''

Expand All @@ -150,6 +170,7 @@ def _previous(self):
try:
self._state = self._states[self._stage]
self._layout[2][0] = self._state.panel()
self._update_button()
except Exception as e:
self._stage += 1
self._error.object = ('Previous stage raised following error:\n\n\t%s: %s'
Expand Down

0 comments on commit 07703ee

Please sign in to comment.