# Seamless: a cell-based interactive workflow framework [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/sjdv1982/seamless-binder-demo/main?labpath=basic-example.ipynb) Seamless is a framework to set up workflows and computations that respond to changes in cells. Cells define the input data as well as the source code of the computations. All cells and computations can be created, edited and connected interactively. The main application domains are data science, scientific computing, software prototyping, and interactive web services. Workflows, computations and results are all represented as directed acyclic graphs that consist of cell checksums. This makes them strongly interoperable and reproducible. ### Documentation: ## Try out Seamless You can try out Seamless in your browser, without any installation, thanks to the Binder project. Click on the badge below: [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/sjdv1982/seamless-binder-demo/main?labpath=basic-example.ipynb) ## Quick installation First, [install Docker](https://docs.docker.com/get-docker/) and [miniconda](https://docs.conda.io/en/latest/miniconda.html). ```bash docker pull rpbs/seamless conda create -n seamless -c rpbs -c conda-forge seamless-cli -y conda activate seamless ``` For more details, see [Installation](https://github.com/sjdv1982/seamless/blob/master/installation.md) ## Basic example First, start **IPython** (`seamless-ipython`) or **Jupyter** (`seamless-jupyter` => create a new Python Notebook). #### 1. Import Seamless in IPython or Jupyter ```python from seamless.highlevel import Context ctx = Context() ``` #### 2. Set up a simple Seamless context ```python def add(a, b): return a + b ctx.a = 10 # ctx.a => Seamless cell ctx.b = 20 # ctx.b => Seamless cell ctx.add = add # ctx.add => Seamless transformer ctx.add.a = ctx.a ctx.add.b = ctx.b ctx.c = ctx.add.result # ctx.c => Seamless cell await ctx.computation() # in a .py file, use "ctx.compute()" instead ctx.c.value ``` ```Out[1]: ``` ```python ctx.a += 5 await ctx.computation() ctx.c.value ``` ```Out[2]: ``` #### 3. Define schemas and validation rules ```python ctx.add.example.a = 0.0 # declares that add.a must be a number ctx.add.example.b = 0.0 def validate(self): assert self.a < self.b ctx.add.add_validator(validate, name="validate") await ctx.computation() print(ctx.add.exception) # Validation passes => exception is None ``` #### 4. Create an API for a Seamless cell ```python def report(self): value = self.unsilk if value is None: print("Sorry, there is no result") else: print("The result is: {}".format(value)) ctx.c.example.report = report await ctx.computation() ctx.c.value.report() ``` ```Out[3]: The result is 35``` #### 5. Mount cells to the file system ```python ctx.a.celltype = "plain" ctx.a.mount("a.json") ctx.b.celltype = "plain" ctx.b.mount("b.json") ctx.c.celltype = "plain" ctx.c.mount("c.json", mode="w") ctx.add.code.mount("code.py") await ctx.translation() ``` #### 6. Share a cell over HTTP ``` python ctx.c.mimetype = "text" ctx.c.share() await ctx.translation() ``` ```bash >>> curl http://localhost:5813/ctx/c 35 ``` #### 7. Control cells from Jupyter ```python from ipywidgets import IntSlider, IntText a = IntSlider(min=-10,max=30) b = IntSlider(min=-10,max=30) c = ctx.c.output() ctx.a.traitlet().link(a) ctx.b.traitlet().link(b) display(a) display(b) display(c) ``` ```Out[4]```
Jupyter widgets (shown only on github.io, not on github.com)
#### 8. Save the entire state of the context ```python # Graph and checksums, as JSON ctx.save_graph("basic-example.seamless") # Checksum-to-buffer cache, as ZIP file ctx.save_zip("basic-example.zip") ``` #### 9. In a new notebook / IPython console: ```python from seamless.highlevel import load_graph ctx = load_graph( "basic-example.seamless", zip="basic-example.zip" ) await ctx.computation() ctx.c.value ``` ```Out[1]: ``` ```python ctx.add.code.value ``` ```Out[2]: 'def add(a, b):\n return a + b'``` ```bash >>> curl http://localhost:5813/ctx/c 35 ``` ##### Documentation