Commit 2c438255 authored by rhaase's avatar rhaase

added code and slides

parent 93f73563
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Phytonic loops"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"input = [1, 3, 4, 7]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Classical loop"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2, 6, 8, 14]\n"
]
}
],
"source": [
"output1 = []\n",
"\n",
"for value in input:\n",
" result = value * 2\n",
" output1 = output1 + [result]\n",
" \n",
"print(output1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pythonic loop"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2, 6, 8, 14]\n"
]
}
],
"source": [
"output2 = [value * 2 for value in input]\n",
"\n",
"print(output2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Pythonic loops 2"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"def process_image(filename):\n",
" print(filename)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Classical loop going through a folder processing all tif images"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"banana0002.tif\n",
"banana0003.tif\n",
"banana0004.tif\n",
"banana0005.tif\n",
"banana0006.tif\n",
"banana0007.tif\n",
"banana0008.tif\n",
"banana0009.tif\n",
"banana0010.tif\n",
"banana0011.tif\n",
"banana0012.tif\n",
"banana0013.tif\n",
"banana0014.tif\n",
"banana0015.tif\n",
"banana0016.tif\n",
"banana0017.tif\n",
"banana0018.tif\n",
"banana0019.tif\n",
"banana0020.tif\n",
"banana0021.tif\n",
"banana0022.tif\n",
"banana0023.tif\n",
"banana0024.tif\n",
"banana0025.tif\n",
"banana0026.tif\n"
]
}
],
"source": [
"import os\n",
"\n",
"# define the location of the folder to go through\n",
"directory = 'C:/structure/teaching/lecture_applied_bioimage_analysis_2020/03_Feature_extraction_and_ImageJ_Macro/example_images/banana/'\n",
"\n",
"# get a list of files in that folder\n",
"file_list = os.listdir(directory)\n",
"\n",
"# go through all files in the folder\n",
"for filename in file_list:\n",
" # if the filename is of a tif-image, print it out\n",
" if filename.endswith(\".tif\"):\n",
" process_image(filename)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pythonic loop going through a folder processing all tif images"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"banana0002.tif\n",
"banana0003.tif\n",
"banana0004.tif\n",
"banana0005.tif\n",
"banana0006.tif\n",
"banana0007.tif\n",
"banana0008.tif\n",
"banana0009.tif\n",
"banana0010.tif\n",
"banana0011.tif\n",
"banana0012.tif\n",
"banana0013.tif\n",
"banana0014.tif\n",
"banana0015.tif\n",
"banana0016.tif\n",
"banana0017.tif\n",
"banana0018.tif\n",
"banana0019.tif\n",
"banana0020.tif\n",
"banana0021.tif\n",
"banana0022.tif\n",
"banana0023.tif\n",
"banana0024.tif\n",
"banana0025.tif\n",
"banana0026.tif\n"
]
},
{
"data": {
"text/plain": [
"[None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None,\n",
" None]"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import os\n",
"\n",
"# define the location of the folder to go through\n",
"directory = 'C:/structure/teaching/lecture_applied_bioimage_analysis_2020/03_Feature_extraction_and_ImageJ_Macro/example_images/banana/'\n",
"\n",
"[process_image(filename) \n",
" for filename in os.listdir(directory)\n",
" if filename.endswith(\".tif\")\n",
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Method parameters documented"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"from skimage.io import imread\n",
"from skimage import filters\n",
"from skimage import measure\n",
"\n",
"def analyse_image(filename, gaussian_blur_sigma, threshold=None):\n",
" \"\"\"\n",
" This function analyses an image by blurring it and applying a threshold.\n",
" \n",
" Parameters\n",
" ----------\n",
" filename\n",
" Image file to open and analyse\n",
" \n",
" gaussian_blur_sigma\n",
" Sigma of a Gaussian blur filter kernel to be \n",
" applied to the image before thresholding\n",
" \n",
" threshold\n",
" Optional, the grey-value threshold to \n",
" differentiate foreground and background\n",
"\n",
" Returns\n",
" -------\n",
" count\n",
" Number of objects in the image\n",
" \n",
" \"\"\"\n",
" \n",
" # load image\n",
" image = imread(filename); \n",
"\n",
" # Gaussian blur\n",
" gaussian_blurred_image = filters.gaussian(image, 5)\n",
"\n",
" # thresholding\n",
" if threshold is None:\n",
" threshold = filters.threshold_otsu(gaussian_blurred_image)\n",
" thresholded_image = gaussian_blurred_image >= threshold\n",
"\n",
" # run connected components analysis\n",
" label_image = measure.label(thresholded_image)\n",
" \n",
" # analyse objects\n",
" table = measure.regionprops_table(label_image)\n",
" \n",
" return len(table[\"label\"])"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"54\n"
]
}
],
"source": [
"print(analyse_image(\"blobs.tif\", 2))"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"54\n"
]
}
],
"source": [
"print(analyse_image(\"blobs.tif\", gaussian_blur_sigma=2))"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
" This function analyses an image by blurring it and applying a threshold.\n",
" \n",
" Parameters\n",
" ----------\n",
" filename\n",
" Image file to open and analyse\n",
" \n",
" gaussian_blur_sigma\n",
" Sigma of a Gaussian blur filter kernel to be \n",
" applied to the image before thresholding\n",
" \n",
" threshold\n",
" Optional, the grey-value threshold to \n",
" differentiate foreground and background\n",
"\n",
" Returns\n",
" -------\n",
" count\n",
" Number of objects in the image\n",
" \n",
" \n"
]
}
],
"source": [
"print(analyse_image.__doc__)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Information hiding, encapsulation\n",
"In classic functional programming, you hand over parameters and calculations are performed:"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"\n",
"def area_of_ellipse(minor_axis, major_axis):\n",
" return math.pi * minor_axis * major_axis / 4\n",
" \n",
"def aspect_ratio_of_ellipse(minor_axis, major_axis):\n",
" return major_axis / minor_axis"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Area: 6.283185307179586\n",
"Aspect ratio: 2.0\n"
]
}
],
"source": [
"minor_axis = 2;\n",
"major_axis = 4;\n",
"\n",
"print(\"Area: \" + str(area_of_ellipse(minor_axis, major_axis)))\n",
"print(\"Aspect ratio: \" + str(aspect_ratio_of_ellipse(minor_axis, major_axis)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Python classes help to combine variables (e.g. minor and major axis) of objects (e.g. an ellipse)."
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"\n",
"class Ellipse:\n",
" \n",
" def __init__(self, minor_axis, major_axis):\n",
" if (minor_axis < major_axis):\n",
" self.minor_axis = minor_axis\n",
" self.major_axis = major_axis\n",
" else:\n",
" self.major_axis = minor_axis\n",
" self.minor_axis = major_axis\n",
" \n",
" def area(self):\n",
" return math.pi * self.minor_axis * self.major_axis / 4\n",
" \n",
" def aspect_ratio(self):\n",
" return self.major_axis / self.minor_axis;\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You enter values once and afterwards, you can ask the object for various properties derived from these values."
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Area: 6.283185307179586\n",
"Aspect ratio: 2.0\n"
]
}
],
"source": [
"e1 = Ellipse(4, 2)\n",
"\n",
"print(\"Area: \" + str(e1.area()))\n",
"print(\"Aspect ratio: \" + str(e1.aspect_ratio()))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Setting up a dataset"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[25.36077192 21.99284607 24.66147459 24.13522414 25.19699394 27.1105588\n",
" 27.21711827 23.99201324 24.62837502 24.00316964 23.97265165 23.69150348\n",
" 23.87474102 24.24951924 22.70964348 27.44811164 23.14164549 23.69577962\n",
" 24.63399963 25.52432004 24.44467109 24.68202734 20.99456432 25.01167432\n",
" 25.31265913 25.98709214 17.59602636 28.80564209 24.74442957 23.09989612\n",
" 24.0190898 22.8590973 22.8516007 25.67153251 25.13355891 26.42321083\n",
" 27.99791641 20.84282366 21.66138292 23.38381399 20.58994995 26.24360199\n",
" 25.36720024 25.46465655 21.03491453 24.78498624 27.36868498 27.48801593\n",
" 25.57688679 25.54842762 26.74737965 22.51636024 25.75046789 20.93175349\n",
" 25.83472988 23.41791145 22.6338715 22.12807181 29.58382288 21.54881035\n",
" 24.60023214 25.09047661 24.75968111 24.64405223 25.7446681 25.201116\n",
" 23.38080789 22.85446879 20.55882516 24.80651406 25.26496377 25.95638214\n",
" 24.69654821 26.11271043 24.57061342 26.21995055 23.57329152 22.38873739\n",
" 23.79337091 25.38534656 24.89694605 22.29055239 23.23316104 26.95960368\n",
" 23.48341966 25.05951226 22.38369459 24.06997003 27.97668846 25.86545142\n",
" 26.85137435 25.39114133 23.21363012 24.38962764 22.08019012 26.99443634\n",
" 24.40998955 26.6712733 25.06958356 27.04129782]\n"
]
}
],
"source": [
"import tomatoes\n",
"\n",
"number_of_tomatoes = 100\n",
"\n",
"ripe_time = tomatoes.ripen(number_of_tomatoes)\n",
"\n",
"print(ripe_time)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Descriptive statistics"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"def do_descriptive_statistics(x):\n",
" mean_x = np.mean(x)\n",
" standard_deviation_x = np.std(x)\n",
"\n",
" print(\"Mean: \" + str(mean_x) + \" +- \" + str(standard_deviation_x))"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Mean: 24.512579751104184 +- 1.9787623359862967\n"
]
}
],
"source": [
"do_descriptive_statistics(ripe_time)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"