Docs
Search…
Jupyter Notebook OME-TIFF example
This example is almost identical to the previous Python OME-TIFF example, but in this case we are using a Jupyter Notebook for coding.

What do I need?

For this example we moved all necessary python code into a Jupyter Notebook. Therefore, only four files are needed to run the module on APEER:
  • module_specification.json: This file defines the in- and outputs of the module as well as the respective UI components.
  • Dockerfile: This file includes the instruction to automatically build a so called image, i.e. it defines what operating-system, applications, etc. the image consists of. You can think of it as a kind of "recipe" that contains all "ingredients" to run the module.
    • Docker automatically loads all necessary python libraries from requirements.txt
  • geometric_transformation.ipynb: The Jupyter Notebook includes all code to geometrically transform an image (e.g. rotate the image).
module_specification.json
Dockerfile
requirements.txt
geometric_transformation.ipynb
The module_specification.json includes two nested objects: spec and the ui. spec defines the in- and outputs of the module. ui defines the respective UI elements that are visible to users when running this module on APEER.
This specific module example has four inputs input_image, angle, shift_x and shift_y and one output output_image. The input angle is rendered as a slider with valid values from 0 to 360. shift_x and shift_y are rendered as textboxes.
Also each of the in- and outputs has a label and a description that are visible to users in the workflow editor & runner.
The easiest way to create the module_specification.json is to use the Module Properties Editor.
module_specification.json
1
{
2
"spec": {
3
"inputs": {
4
"input_image": {
5
"type:file": {}
6
},
7
"angle": {
8
"type:number": {
9
"lower_inclusive": 0,
10
"upper_inclusive": 360
11
},
12
"default": 0
13
},
14
"shift_x": {
15
"type:number": {},
16
"default": 0
17
},
18
"shift_y": {
19
"type:number": {},
20
"default": 0
21
}
22
},
23
"outputs": {
24
"output_image": {
25
"type:file": {}
26
}
27
}
28
},
29
"ui": {
30
"inputs": {
31
"input_image": {
32
"index": 0,
33
"widget:none": null,
34
"label": "Input image"
35
},
36
"angle": {
37
"index": 1,
38
"label": "Rotation Angle in degrees",
39
"widget:slider": {
40
"step": 0.1
41
}
42
},
43
"shift_x": {
44
"index": 2,
45
"label": "Shift x in px",
46
"description": "Shift x in px (must be integer number)",
47
"widget:textbox": {
48
}
49
},
50
"shift_y": {
51
"index": 3,
52
"label": "Shift y in px",
53
"description": "Shift y in px (must be integer number)",
54
"widget:textbox": {
55
}
56
}
57
},
58
"outputs": {
59
"output_image": {
60
"label": "Output image",
61
"description": "The processed image",
62
"index": 4
63
}
64
}
65
}
66
}
Copied!
The Dockerfile loads all necessary "ingredients". The python libraries are specified in requirements.txt
1
# The dockerfile begins with defining an image FROM which the build process starts.
2
# Since our module is based on python 3.6, we use python:3.6 as our base image.
3
# You can find trusted docker contains at https://store.docker.com/.
4
FROM python:3.6
5
6
# WORKDIR changes the active directory of the container to a specific location.
7
# In case you need to run commands from or in a particular location.
8
WORKDIR /usr/src/app
9
10
# COPY allows you to copy any file from host to the container.
11
# In this case the file requirement.txt is copied to the root directory of the container
12
COPY requirements.txt .
13
14
# RUN allows you to run the command from the within the container when it's first created.
15
# It is used to build the image. These can be any command line instruction you wish
16
# if you have the dependency to support it. In our case we want to install the
17
# additional libraries mentioned in requirements.txt
18
RUN pip install --no-cache-dir -r requirements.txt
19
20
# Here we are copying all our files to the root directory of the container
21
COPY geometric_transformation.ipynb .
22
COPY module_specification.json .
23
24
# CMD command is similar to RUN. However unlike RUN, CMD is not executed during build, but when a container is instantiated.
25
# Therefore, it should be considered as an initial, default command that gets executed when container starts.
26
# In this example, we would like to run our Jupyter Notebook when the container starts.
27
CMD runipy ./geometric_transformation.ipynb
Copied!
This Jupyter Notebook requires the following python libraries:
1
apeer-dev-kit>=1.0.6,<2
2
apeer-ometiff-library>=1.3.1,<2
3
scikit-image==0.15.0
4
scipy==1.1.0
5
numpy==1.15.4
6
notebook==6.0.2
7
runipy==0.1.5
Copied!
The Jupyter Notebook contains the python code for geometric transformation.

1. Import all necessary libraries

  • apeer_ometiff_library is used to read & write ome-tiff files in python
  • To install the library on your local machine run: pip install apeer-ometiff-library
1
import os
2
from scipy import ndimage as ndi
3
from apeer_ometiff_library import io, processing
4
import skimage
5
import numpy as np
Copied!

2. Define your function (in this case geometric transformation for every channel of the input image)

1
def _geometric_transformation(image2d, angle, shift_x, shift_y):
2
image_shifted = ndi.shift(image2d, (float(shift_x), float(shift_y)))
3
image_rotated = ndi.rotate(image_shifted, angle, reshape=False)
4
return image_rotated
Copied!

3. Apply your function to the whole image independent from the number of channels

1
def execute(image_path, angle, shift_x, shift_y):
2
3
image_name = os.path.basename(image_path)
4
5
#Distinguish between ome-tiff and non-ome-tiff files
6
if image_path.lower().endswith('.ome.tiff') or image_path.lower().endswith('.ome.tif'):
7
# Read original image
8
(array5d, omexml) = io.read_ometiff(image_path)
9
# Return value is an 5D Array of order (T, Z, C, X, Y)
10
# Apply 2D function to 5D array
11
arrayOut5d = processing.apply_2d_trafo(_geometric_transformation,
12
array5d,
13
angle=angle,
14
shift_x=shift_x,
15
shift_y=shift_y)
16
17
# In case you have a 3D function that acts on a whole Z-Stack use this code:
18
# The order of the 3D input image of trafo3D should be: (Z,X,Y)
19
#arrayOut5D = processing.apply_3d_trafo_zstack(trafo3d, array5D, angle)
20
21
# In case you have a 3D function that acts on a whole RGB image use this code:
22
# The order of the 3D input image of trafo3D should be: (C,X,Y)
23
#arrayOut5D = processing.apply_3D_trafo_rbg(trafo3d, array5D, angle)
24
25
io.write_ometiff(image_name, arrayOut5d, omexml)
26
else:
27
# Read original image
28
array = skimage.io.imread(image_path)
29
if array.ndim == 3: # Process image with color channels
30
result = np.zeros_like(array)
31
for channel in range(array.shape[2]):
32
result[:,:,channel] = _geometric_transformation(array[:,:,channel], angle, shift_x, shift_y)
33
elif array.ndim == 2: # Process grayscale image
34
result = _geometric_transformation(array, angle, shift_x, shift_y)
35
# Write modified image
36
skimage.io.imsave(image_name, result)
37
38
return {'output_image': image_name}
Copied!

4. (Optionally) Enable the following lines for local testing

1
#execute("input/nucleiTubolin.ome.tiff", 45.0, 20, 50)
2
#execute("input/nucleiTubolin.jpg", 45.0, 20, 50)
Copied!

5. Add the following lines to make your code executable on the APEER platform

Note: please make sure that the in- and outputs are in line with your module specification file (module_specification.json). In this case the inputs are: input_image, angle, shift_x and shift_y. The respective output is: output_image.
1
from apeer_dev_kit import adk
2
3
inputs = adk.get_inputs()
4
5
outputs = execute(inputs['input_image'], inputs['angle'], inputs['shift_x'], inputs['shift_y'])
6
7
adk.set_file_output('output_image', outputs['output_image'])
8
9
adk.finalize()
Copied!
Jupyter Notebook Example.zip
1019KB
Binary
Jupyter Notebook OME-TIFF example
You can also download the source code by creating a new 'Jupyter Notebook OME-TIFF Example' Module in APEER.

Running the module on APEER

After pushing your code to the APEER platform via git, you can create a workflow to test your module, e.g.:
All inputs are rendered according to the module_specification.json file. The respective module view in the workflow runner is:
Congratulations! You just created your first Jupyter Notebook Module on APEER. If you share it with other people, they can easily re-use it, even without having any coding skills!

You couldn't find all the information you need? Contact us!

If you need help, just check out our FAQ. For any further questions please contact us at [email protected] or have a look at How-tos section in our blog or follow us on Twitter to stay up to date.
Last modified 2yr ago