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

Multiple Fixes #9

Merged
merged 15 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "vendor/juxtapose"]
path = vendor/juxtapose
url = https://github.com/NUKnightLab/juxtapose
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,14 @@ Formatting with black can be done this way:
2. `black --python-cell-magics splity splitview_magic.ipynb`


## Developer Installation

1. `git clone --recurse https://github.com/kolibril13/jupyter-splitview`
2. `poetry install`

## Changelog

## Milestones for >0.0.5
## Milestones for >0.0.5

* Handle cases where n ≠ 2 images. Currently: All further img are ignored.
* implement tests, find out how to test a magic class
Expand Down
435 changes: 414 additions & 21 deletions example_notebook.ipynb

Large diffs are not rendered by default.

20 changes: 18 additions & 2 deletions jupyter_splitview/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from pathlib import Path

from .sw_cellmagic import SplitViewMagic
from IPython import get_ipython # register cell magic
from IPython import get_ipython
from IPython.core.display import HTML
from IPython.display import display
import pkg_resources

__version__: str = pkg_resources.get_distribution(__name__).version
Expand All @@ -10,5 +14,17 @@
ipy = get_ipython()
ipy.register_magics(SplitViewMagic)

css_path = Path(__file__).parents[1] / "vendor/juxtapose/build/css/juxtapose.css"
js_path = Path(__file__).parents[1] / "vendor/juxtapose/build/js/juxtapose.min.js"

html_code = f"""
<style>{css_path.read_text()}</style>
<script>{js_path.read_text()}</script>
"""
display(HTML(html_code))


except AttributeError:
print("Can not load SplitViewMagic because this is not a notebook")
print("Can not load SplitViewMagic because this is not a notebook")


43 changes: 43 additions & 0 deletions jupyter_splitview/inject.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<div id="splitview_wrapper_{{ cell_id }}">
<div id="splitview_{{ cell_id }}"></div>
</div>

<script>
slider = new juxtapose.JXSlider("#splitview_{{ cell_id }}",
[
{
src: "{{ image_data_urls[0] }}",
},
{
src: "{{ image_data_urls[1] }}",
}
],
{
animate: true,
showLabels: false,
showCredits: false,
startingPosition: "{{ slider_position }}",
makeResponsive: true,
// undocumented shit
callback: (jx_slider) => {
// remove juxtapose.js link and logo in bottom left corner
jx_slider.slider.removeChild(jx_slider.labCredit);
},
});
</script>

<style>
#splitview_wrapper_{{ cell_id }} {
position: relative;
padding-top: {{ wrapper_height }}px;
}

#splitview_{{ cell_id }} {
height: {{ height }}px;
width: auto;
top: 1%;
left: 1%;
position: absolute;
}
</style>

46 changes: 29 additions & 17 deletions jupyter_splitview/sw_cellmagic.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import io
import os
from base64 import b64decode

from IPython.core import magic_arguments
Expand All @@ -8,6 +9,15 @@
from IPython.utils.capture import capture_output
from PIL import Image

from jinja2 import Template, StrictUndefined

g_cell_id = 0

def compile_template(in_file: str, **variables) -> str:
with open(f"{in_file}", "r", encoding="utf-8") as file:
template = Template(file.read(), undefined=StrictUndefined)
return template.render(**variables)


@magics_class
class SplitViewMagic(Magics):
Expand All @@ -16,16 +26,15 @@ class SplitViewMagic(Magics):
"--position",
"-p",
default="50%",
help=("The position where the slider starts"),
help=("The start position of the slider"),
)
@magic_arguments.argument(
"--height",
"-h",
default="300",
help=(
"The height that the widget has. The width will be adjusted automatically. \
If height is choosen 'auto', the height will be defined by the resolution \
in vertical direction of the first image."
"The widget's height. The width will be adjusted automatically. \
If height is `auto`, the vertical resolution of the first image is used."
),
)
@cell_magic
Expand All @@ -43,7 +52,7 @@ def splity(self, line, cell):
png_bytes_data = data["image/png"]
out_images_base64.append(png_bytes_data)

# get the parameters the configure the widget
# get the parameters that configure the widget
args = magic_arguments.parse_argstring(SplitViewMagic.splity, line)

slider_position = args.position
Expand All @@ -53,17 +62,20 @@ def splity(self, line, cell):
imgdata = b64decode(out_images_base64[0])
# maybe possible without the PIL dependency?
im = Image.open(io.BytesIO(imgdata))
width, height = im.size
widget_height = height
widget_height = im.size[1]

html_code = f"""
<div class="outer_layer" style="position: relative; padding-top: {int(widget_height)+3}px;">
<div class="juxtapose" data-startingposition="{slider_position}" style="height: {int(widget_height)}px;; width: auto; top: 1%; left: 1%; position: absolute;">
<img src="data:image/jpeg;base64,{out_images_base64[0]}" />' <img src="data:image/jpeg;base64,{out_images_base64[1]}" />'
</div>
</div>
<script src="https://cdn.knightlab.com/libs/juxtapose/latest/js/juxtapose.min.js"></script>
<link rel="stylesheet" href="https://cdn.knightlab.com/libs/juxtapose/latest/css/juxtapose.css" />
"""
image_data_urls = [f"data:image/jpeg;base64,{base64.strip()}" for base64 in out_images_base64]

# every juxtapose html node needs unique id
global g_cell_id
html_code = compile_template(
os.path.join((os.path.dirname(__file__)), "inject.html"),
cell_id=g_cell_id,
image_data_urls=image_data_urls,
slider_position=slider_position,
wrapper_height=int(widget_height)+4,
height=int(widget_height),
)
g_cell_id += 1
display(HTML(html_code))

8 changes: 7 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,26 @@ version = "0.0.4"
description = "Making before/after image sliders in JupyterLab"
authors = ["kolibril13 <[email protected]>"]
license = "MIT"
include = [
"vendor/juxtapose/build/css/juxtapose.css",
"vendor/juxtapose/build/js/juxtapose.min.js",
]

[tool.poetry.dependencies]
python = ">=3.8,<3.11"
ipython = ">=7.0.0"
ipykernel = ">=6.13.0"
Pillow = ">=9.1.0"
Jinja2 = "^3.1.2"

[tool.poetry.dev-dependencies]
black = {extras = ["jupyter"], version = ">=22.3.0"}
black = { extras = ["jupyter"], version = ">=22.3.0" }
matplotlib = ">=3.5.1"
scipy = ">=1.8.0"
scikit-image = ">=0.19.2"
pytest = ">=7.1.2"
isort = ">=5.10.1"
jupyterlab = "^3.4.3"

[build-system]
requires = ["poetry-core>=1.0.0"]
Expand Down
1 change: 1 addition & 0 deletions vendor/juxtapose
Submodule juxtapose added at 975e8f