diff --git a/_includes/image_file_formats/open_czi_bioio.py b/_includes/image_file_formats/open_czi_bioio.py index c1fbfe2b..be755d4e 100644 --- a/_includes/image_file_formats/open_czi_bioio.py +++ b/_includes/image_file_formats/open_czi_bioio.py @@ -4,180 +4,44 @@ # conda create -n ImageFileFormats python=3.10 # activate ImageFileFormat # pip install bioio bioio-tifffile bioio-lif bioio-czi bioio-ome-tiff bioio-ome-zarr notebook +# Note: for only dealing with .czi just do pip install bioio bioio-czi -# TODO -# - Change the below code to only open the CZI image -# - Implement that it opens both images that are contained in the file (see ImageJ GUI activity) - -# %% -# Load .tif file with minimal metadata -# - Observe that BioImage chooses the correct reader plugin -# - Observe that the return object is not the image matrix -from bioio import BioImage -image_url = 'https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__nuclei_PLK1_control.tif' -bioimage = BioImage(image_url) -print(bioimage) -print(type(bioimage)) - -# %% -# Print some onject attributes -# - Observe that the object is 5 dimensional with most dimensions being empty -# - Observe that the dimension order is always time, channel, z, y, x, (TCZYX) -print(bioimage.dims) -print(bioimage.shape) -print(f'Dimension order is: {bioimage.dims.order}') -print(type(bioimage.dims.order)) -print(f'Size of X dimension is: {bioimage.dims.X}') - -# %% -# Extract image data -# - Observe that the returned numpy.array is still 5 dimensional -image_data = bioimage.data -print(type(image_data)) -print(image_data) -print(image_data.shape) - -# %% -# Extract specific part of image data -# - Observe that numpy.array is reduced to populated dimensions only -yx_image_data = bioimage.get_image_data('YX') -print(type(yx_image_data)) -print(yx_image_data) -print(yx_image_data.shape) - -# %% -# Access pixel size -import numpy as np -print(bioimage.physical_pixel_sizes) -print(f'An pixel has a length of {np.round(bioimage.physical_pixel_sizes.X,2)} microns in X dimension.') - -# %% -# Access general metadata -print(type(bioimage.metadata)) -print(bioimage.metadata) - -# %% -# Load .tif file with extensive metadata -image_url = "https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_16bit__collagen.md.tif" -bioimage = BioImage(image_url) -print(bioimage) -print(type(bioimage)) - -# - Observe that the image is larger than the previous -print(bioimage.dims) - -# %% -# Access image and reduce to only populated dimensions -yx_image_data = bioimage.data.squeeze() -print(type(yx_image_data)) -print(yx_image_data) -print(yx_image_data.shape) - -# %% -# Access pixel size -print(bioimage.physical_pixel_sizes) -print(f'An pixel has a length of {np.round(bioimage.physical_pixel_sizes.Y,2)} microns in Y dimension.') - -# Access general metadata -# - Observe that metadata are more extensive than in the previous image -print(type(bioimage.metadata)) -print(bioimage.metadata) - -# %% -# Load .lif file -# - Observe that BioImage chooses the correct reader plugin -# - Observe that the return object has 4 different channels -# - Observe that the general metadata are an abstract element -image_url = "https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_xyc__two_images.lif" -bioimage = BioImage(image_url) -print(bioimage) -print(type(bioimage)) -print(bioimage.dims) -print(bioimage.metadata) -print(type(bioimage.metadata)) - -# %% -# Access channel information -print(bioimage.channel_names) - -# %% -# Access image data for all channels -img_4channel = bioimage.data.squeeze() - -# Alternative -img_4channel = bioimage.get_image_data('CYX') - -# - Observe that numpy.array shape is 3 dimensional representing channel,y,x -print(img_4channel.shape) - -# Access only one channel -img_1channel = bioimage.get_image_data('YX',C=0) - -# Alternative -img_1channel = img_4channel[0] - -# - Observe that numpy.array shape is 2 dimensional representing y,x -print(img_1channel.shape) - -# %% -# Access different images in one image file (scenes) -# - Observe that one image file can contain several scenes -# - Observe that they can be different in various aspects -print(bioimage.scenes) -print(f'Current scene: {bioimage.current_scene}') - -# - Observe that the image in the current scene as 4 channel and Y/X dimensions have the size of 1024 -print(bioimage.dims) -print(bioimage.physical_pixel_sizes) - -# Switch to second scene -# - Observe that the image in the other scene as only one channel and Y/X dimensions are half as large as the first scene -# - Observe that the pixel sizes are doubled -bioimage.set_scene(1) -print(bioimage.dims) -print(bioimage.physical_pixel_sizes) # %% # Load .czi file # file needs first to be downloaded from https://github.com/NEUBIAS/training-resources/raw/master/image_data/xyz__multiple_images.czi # save file in the same directory as this notebook # - Observe that BioImage chooses the correct reader plugin -# - Observe that the return object has a z dimension -bioimage = BioImage('/Users/fschneider/skimage-napari-tutorial/ExampleImages/xyz__multiple_images.czi') +from bioio import BioImage +bioimage = BioImage('~/skimage-napari-tutorial/ExampleImages/xyz__multiple_images.czi') print(bioimage) print(type(bioimage)) # %% -# little excersise in between -# Access image dimensions -print(bioimage.dims) - -# Access general metadata -# - Observe that metadata are abstract -print(bioimage.metadata) -print(type(bioimage.metadata)) - -# Access pixel size -print(bioimage.physical_pixel_sizes) - -# Access image data for all channels -img_3d = bioimage.data.squeeze() - -# Alternative -img_3d = bioimage.get_image_data('ZYX') - -# - Observe that numpy.array shape is 3 dimensional representing z,y,x -print(img_3d.shape) - -# Access only one channel -img_2d = bioimage.get_image_data('YX',Z=0) - -# Alternative -img_2d = img_3d[0] - -# - Observe that numpy.array shape is 2 dimensional representing y,x -print(img_2d.shape) +# Inspect number of images in object +print(bioimage.scenes) # %% -# little excercise: -# paticipants should try to open one of their files with python +# Inspect both images in the object +for image in bioimage.scenes: + print(f'Image name: {image}') + # Select image: + bioimage.set_scene(image) + # Inspect dimension and shape of image + print(f'Image dimension: {bioimage.dims}') + print(f'Dimension order is: {bioimage.dims.order}') + print(f'Image shape: {bioimage.shape}') + # Extract image data (5D) + image_data = bioimage.data + print(f'Image type: {type(image_data)}') + print(f'Image array shape: {image_data.shape}') + # Extract specific image part + image_data = bioimage.get_image_data('YX') + print(f'Image type: {type(image_data)}') + print(f'Image array shape: {image_data.shape}') + # Read pixel size + print(f'Pixel size: {bioimage.physical_pixel_sizes}') + # Read metadata + print(f'Metadata type: {type(bioimage.metadata)}') + print(f'Metadata: {bioimage.metadata}') + print('\n') diff --git a/_includes/image_file_formats/open_em_tiff_series_bioio.py b/_includes/image_file_formats/open_em_tiff_series_bioio.py index c1fbfe2b..de318a93 100644 --- a/_includes/image_file_formats/open_em_tiff_series_bioio.py +++ b/_includes/image_file_formats/open_em_tiff_series_bioio.py @@ -1,183 +1,34 @@ # %% -# Open a CZI image file +# Open a TIFF series # minimal conda env for this module # conda create -n ImageFileFormats python=3.10 # activate ImageFileFormat # pip install bioio bioio-tifffile bioio-lif bioio-czi bioio-ome-tiff bioio-ome-zarr notebook +# Note: for only dealing with .tif just do pip install bioio bioio-tifffile -# TODO -# - Change the below code to only open the CZI image -# - Implement that it opens both images that are contained in the file (see ImageJ GUI activity) # %% -# Load .tif file with minimal metadata -# - Observe that BioImage chooses the correct reader plugin -# - Observe that the return object is not the image matrix -from bioio import BioImage -image_url = 'https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__nuclei_PLK1_control.tif' -bioimage = BioImage(image_url) -print(bioimage) -print(type(bioimage)) - -# %% -# Print some onject attributes -# - Observe that the object is 5 dimensional with most dimensions being empty -# - Observe that the dimension order is always time, channel, z, y, x, (TCZYX) -print(bioimage.dims) -print(bioimage.shape) -print(f'Dimension order is: {bioimage.dims.order}') -print(type(bioimage.dims.order)) -print(f'Size of X dimension is: {bioimage.dims.X}') +# create list of image file names and order them +from pathlib import Path +path_to_files = Path('/Users/fschneider/Training/training-resources/image_data/xyz_8bit__em_volume_tiff_series') +tiff_files = [file for file in path_to_files.glob("*.tif")] +# order files +tiff_files.sort() +print(tiff_files) # %% -# Extract image data -# - Observe that the returned numpy.array is still 5 dimensional -image_data = bioimage.data -print(type(image_data)) -print(image_data) -print(image_data.shape) +# Open each image with BioIO +from bioio import BioImage +bioimages = [BioImage(file) for file in tiff_files] -# %% -# Extract specific part of image data -# - Observe that numpy.array is reduced to populated dimensions only -yx_image_data = bioimage.get_image_data('YX') -print(type(yx_image_data)) -print(yx_image_data) -print(yx_image_data.shape) +# Print pixel sizes +for bioimage in bioimages: + print(bioimage.physical_pixel_sizes) # %% -# Access pixel size +# Concatenate in 3D volume +em_volume = [bioimage.data.squeeze() for bioimage in bioimages] +# make numpy array import numpy as np -print(bioimage.physical_pixel_sizes) -print(f'An pixel has a length of {np.round(bioimage.physical_pixel_sizes.X,2)} microns in X dimension.') - -# %% -# Access general metadata -print(type(bioimage.metadata)) -print(bioimage.metadata) - -# %% -# Load .tif file with extensive metadata -image_url = "https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_16bit__collagen.md.tif" -bioimage = BioImage(image_url) -print(bioimage) -print(type(bioimage)) - -# - Observe that the image is larger than the previous -print(bioimage.dims) - -# %% -# Access image and reduce to only populated dimensions -yx_image_data = bioimage.data.squeeze() -print(type(yx_image_data)) -print(yx_image_data) -print(yx_image_data.shape) - -# %% -# Access pixel size -print(bioimage.physical_pixel_sizes) -print(f'An pixel has a length of {np.round(bioimage.physical_pixel_sizes.Y,2)} microns in Y dimension.') - -# Access general metadata -# - Observe that metadata are more extensive than in the previous image -print(type(bioimage.metadata)) -print(bioimage.metadata) - -# %% -# Load .lif file -# - Observe that BioImage chooses the correct reader plugin -# - Observe that the return object has 4 different channels -# - Observe that the general metadata are an abstract element -image_url = "https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_xyc__two_images.lif" -bioimage = BioImage(image_url) -print(bioimage) -print(type(bioimage)) -print(bioimage.dims) -print(bioimage.metadata) -print(type(bioimage.metadata)) - -# %% -# Access channel information -print(bioimage.channel_names) - -# %% -# Access image data for all channels -img_4channel = bioimage.data.squeeze() - -# Alternative -img_4channel = bioimage.get_image_data('CYX') - -# - Observe that numpy.array shape is 3 dimensional representing channel,y,x -print(img_4channel.shape) - -# Access only one channel -img_1channel = bioimage.get_image_data('YX',C=0) - -# Alternative -img_1channel = img_4channel[0] - -# - Observe that numpy.array shape is 2 dimensional representing y,x -print(img_1channel.shape) - -# %% -# Access different images in one image file (scenes) -# - Observe that one image file can contain several scenes -# - Observe that they can be different in various aspects -print(bioimage.scenes) -print(f'Current scene: {bioimage.current_scene}') - -# - Observe that the image in the current scene as 4 channel and Y/X dimensions have the size of 1024 -print(bioimage.dims) -print(bioimage.physical_pixel_sizes) - -# Switch to second scene -# - Observe that the image in the other scene as only one channel and Y/X dimensions are half as large as the first scene -# - Observe that the pixel sizes are doubled -bioimage.set_scene(1) -print(bioimage.dims) -print(bioimage.physical_pixel_sizes) - -# %% -# Load .czi file -# file needs first to be downloaded from https://github.com/NEUBIAS/training-resources/raw/master/image_data/xyz__multiple_images.czi -# save file in the same directory as this notebook -# - Observe that BioImage chooses the correct reader plugin -# - Observe that the return object has a z dimension -bioimage = BioImage('/Users/fschneider/skimage-napari-tutorial/ExampleImages/xyz__multiple_images.czi') -print(bioimage) -print(type(bioimage)) - -# %% -# little excersise in between -# Access image dimensions -print(bioimage.dims) - -# Access general metadata -# - Observe that metadata are abstract -print(bioimage.metadata) -print(type(bioimage.metadata)) - -# Access pixel size -print(bioimage.physical_pixel_sizes) - -# Access image data for all channels -img_3d = bioimage.data.squeeze() - -# Alternative -img_3d = bioimage.get_image_data('ZYX') - -# - Observe that numpy.array shape is 3 dimensional representing z,y,x -print(img_3d.shape) - -# Access only one channel -img_2d = bioimage.get_image_data('YX',Z=0) - -# Alternative -img_2d = img_3d[0] - -# - Observe that numpy.array shape is 2 dimensional representing y,x -print(img_2d.shape) - -# %% -# little excercise: -# paticipants should try to open one of their files with python +em_volume = np.stack(em_volume,axis=0) +print(em_volume.shape) diff --git a/_includes/image_file_formats/open_lif_bioio.py b/_includes/image_file_formats/open_lif_bioio.py new file mode 100644 index 00000000..afc674a5 --- /dev/null +++ b/_includes/image_file_formats/open_lif_bioio.py @@ -0,0 +1,46 @@ +# %% +# Open a CZI image file +# minimal conda env for this module +# conda create -n ImageFileFormats python=3.10 +# activate ImageFileFormat +# pip install bioio bioio-tifffile bioio-lif bioio-czi bioio-ome-tiff bioio-ome-zarr notebook +# Note: for only dealing with .lif just do pip install bioio bioio-lif + + +# %% +# Load .lif file +# - Observe that BioImage chooses the correct reader plugin +from bioio import BioImage +image_url = "https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_xyc__two_images.lif" +bioimage = BioImage(image_url) +print(bioimage) +print(type(bioimage)) + +# %% +# Inspect number of images in object +print(bioimage.scenes) + +# %% +# Inspect both images in the object +for image in bioimage.scenes: + print(f'Image name: {image}') + # Select image: + bioimage.set_scene(image) + # Inspect dimension and shape of image + print(f'Image dimension: {bioimage.dims}') + print(f'Dimension order is: {bioimage.dims.order}') + print(f'Image shape: {bioimage.shape}') + # Extract image data (5D) + image_data = bioimage.data + print(f'Image type: {type(image_data)}') + print(f'Image array shape: {image_data.shape}') + # Extract specific image part + image_data = bioimage.get_image_data('YX') + print(f'Image type: {type(image_data)}') + print(f'Image array shape: {image_data.shape}') + # Read pixel size + print(f'Pixel size: {bioimage.physical_pixel_sizes}') + # Read metadata + print(f'Metadata type: {type(bioimage.metadata)}') + print(f'Metadata: {bioimage.metadata}') + print('\n') diff --git a/_includes/image_file_formats/open_tif_bioio.py b/_includes/image_file_formats/open_tif_bioio.py new file mode 100644 index 00000000..817fb10b --- /dev/null +++ b/_includes/image_file_formats/open_tif_bioio.py @@ -0,0 +1,52 @@ +# %% +# Open a tif image file +# minimal conda env for this module +# conda create -n ImageFileFormats python=3.10 +# activate ImageFileFormat +# pip install bioio bioio-tifffile bioio-lif bioio-czi bioio-ome-tiff bioio-ome-zarr notebook +# Note: for only dealing with .tif just do pip install bioio bioio-tifffile + + +# %% +# Load .tif file +# - Observe that BioImage chooses the correct reader plugin +from bioio import BioImage +image_url = 'https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__nuclei_PLK1_control.tif' +bioimage = BioImage(image_url) +print(bioimage) +print(type(bioimage)) + +# %% +# Inspect dimension and shape of image +print(f'Image dimension: {bioimage.dims}') +print(f'Dimension order is: {bioimage.dims.order}') +print(f'Image shape: {bioimage.shape}') + +# %% +# Extract image data (5D) +image_data = bioimage.data +print(f'Image type: {type(image_data)}') +print(f'Image array shape: {image_data.shape}') +# Extract specific image part +image_data = bioimage.get_image_data('YX') +print(f'Image type: {type(image_data)}') +print(f'Image array shape: {image_data.shape}') + +# %% +# Read pixel size +print(f'Pixel size: {bioimage.physical_pixel_sizes}') +# Read metadata +print(f'Metadata type: {type(bioimage.metadata)}') +print(f'Metadata: {bioimage.metadata}') + +# %% +# Load .tif file with extensive metadata +image_url = "https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_16bit__collagen.md.tif" +bioimage = BioImage(image_url) + +# %% +# Read pixel size +print(f'Pixel size: {bioimage.physical_pixel_sizes}') +# Read metadata +print(f'Metadata type: {type(bioimage.metadata)}') +print(f'Metadata: {bioimage.metadata}') \ No newline at end of file diff --git a/_includes/script_for_loop/script_advanced_for_loop.py b/_includes/script_for_loop/script_advanced_for_loop.py new file mode 100644 index 00000000..a339ec69 --- /dev/null +++ b/_includes/script_for_loop/script_advanced_for_loop.py @@ -0,0 +1,98 @@ +# %% +# Anything iterable can be iterated over with a for loop +# Observe that: +# - list content don't matter +# - that the iterator will always be overwritten by the next item +for i in ['a','b','c',1,2,3,[1,2,3],1.5,2.7]: + print(f'"i" has the value "{i}" and type "{type(i)}"') + +# Iterate over two or more list (with the same length) +# e.g. iterate over a list of coordinates +import numpy as np +image = np.random.randint(0,255,100).reshape(10,10) +x_coordinates = range(10) +y_coordinates = range(10) +for y,x in zip(y_coordinates,x_coordinates): + print(f'At position x: {x} and y: {y} the intensity value is: {image[y,x]}.') + +# %% +# list comprehension +squares = [] +for i in range(10): + squares.append(i**2) +print(squares) +# use list comprehension +squares = [i**2 for i in range(10)] +print(squares) + +# usefull for creating an filepath iterable +from pathlib import Path +[file for file in Path().cwd().iterdir()] + +# %% +# for loop with if +for x in range(10): + if x != 0: + print(f'X: {x}, 1/X: {1/x}') + +# for loop with if and else +for x in range(10): + if x == 0: + print(f'X: {x}, 1/X: Division by {x} not defined.') + else: + print(f'X: {x}, 1/X: {1/x}') + +# %% +# for loop with continue and break +# Usage: +# - skip files/data for processing +# - debugging +# continue +for x in range(10): + if x==0: + continue + print(f'X: {x}, 1/X: {1/x}') + +# break +for x in range(10): + if x==3: + break + print(x) + +# %% +# Nested loops +for x in range(1,4): + for y in range(1,4): + print(f'X: {x}, Y: {y}, X*Y: {x*y}') + +# Nested lists +for sublist in [[1,2,3],[4,5,6],[7,8,9]]: + for i in sublist: + print(i) + +# np.array +# Observe that you iterate only over the first dimension when using simple loop +array = np.random.randint(0,10,100).reshape(10,10) +print(array.shape) +for i in array: + print(i) + +for row in array: + for i in row: + print(i) + +# %% +# Looping over pandas DataFrame +# Observe that +# - looping with iterrows always gives an index +# - the second variable will always be a pandas Series object +import pandas as pd +df = pd.DataFrame({ + 'a':[1,2,3], + 'b':[4,5,6]}) +print(df) +for i,row in df.iterrows(): + print(type(row)) + value_a = row['a'] + value_b = row['b'] + print(f'Row index {i}\nColumn value "a": {value_a} and Column value "b": {value_b}') \ No newline at end of file diff --git a/_includes/script_for_loop/script_for_loop_python.py b/_includes/script_for_loop/script_for_loop_python.py index 2c8920cf..39cf436b 100644 --- a/_includes/script_for_loop/script_for_loop_python.py +++ b/_includes/script_for_loop/script_for_loop_python.py @@ -42,14 +42,6 @@ for i in range(10): print(i) -# %% -# Anything iterable can be iterated over with a for loop -# Observe that: -# - list content don't matter -# - that the iterator will always be overwritten by the next item -for i in ['a','b','c',1,2,3,[1,2,3],1.5,2.7]: - print(f'"i" has the value "{i}" and type "{type(i)}"') - # %% # Use a for loop for the example in the beginning # First pack images into a list for looping over @@ -70,95 +62,6 @@ for i in range(number_of_images): print(f'Image {i} has an avg intensity of {image_list[i].mean()}.') -# Iterate over two or more list (with the same length) -for i,image in zip(range(number_of_images),image_list): - print(f'Image {i} has an avg intensity of {image.mean()}.') - # Iterate with additional index for i,image in enumerate(image_list): print(f'Image {i} has an avg intensity of {image.mean()}.') - -# %% -# For loops but advanced - -# %% -# list comprehension -squares = [] -for i in range(10): - squares.append(i**2) -print(squares) -# use list comprehension -squares = [i**2 for i in range(10)] -print(squares) - -# usefull for creating an filepath iterable -from pathlib import Path -[file for file in Path().cwd().iterdir()] - -# %% -# for loop with if -for x in range(10): - if x != 0: - print(f'X: {x}, 1/X: {1/x}') - -# for loop with if and else -for x in range(10): - if x == 0: - print(f'X: {x}, 1/X: Division by {x} not defined.') - else: - print(f'X: {x}, 1/X: {1/x}') - -# %% -# for loop with continue and break -# Usage: -# - skip files/data for processing -# - debugging -# continue -for x in range(10): - if x==0: - continue - print(f'X: {x}, 1/X: {1/x}') - -# break -for x in range(10): - if x==3: - break - print(x) - -# %% -# Nested loops -for x in range(1,4): - for y in range(1,4): - print(f'X: {x}, Y: {y}, X*Y: {x*y}') - -# Nested lists -for sublist in [[1,2,3],[4,5,6],[7,8,9]]: - for i in sublist: - print(i) - -# np.array -# Observe that you iterate only over the first dimension when using simple loop -array = np.random.randint(0,10,100).reshape(10,10) -print(array.shape) -for i in array: - print(i) - -for row in array: - for i in row: - print(i) - -# %% -# Looping over pandas DataFrame -# Observe that -# - looping with iterrows always gives an index -# - the second variable will always be a pandas Series object -import pandas as pd -df = pd.DataFrame({ - 'a':[1,2,3], - 'b':[4,5,6]}) -print(df) -for i,row in df.iterrows(): - print(type(row)) - value_a = row['a'] - value_b = row['b'] - print(f'Row index {i}\nColumn value "a": {value_a} and Column value "b": {value_b}') \ No newline at end of file diff --git a/_modules/script_for_loop.md b/_modules/script_for_loop.md index 735a9143..f9bad817 100644 --- a/_modules/script_for_loop.md +++ b/_modules/script_for_loop.md @@ -37,6 +37,7 @@ activities: - ["ImageJ Macro, example no loop", "script_for_loop/activities/script_for_loop_measure_distances_noloop.ijm"] - ["ImageJ Macro, example with loop", "script_for_loop/activities/script_for_loop_measure_distances_withloop.ijm"] - ["Python, for loop", "script_for_loop/script_for_loop_python.py"] + - ["Python, advanced for loop", "script_for_loop/script_advanced_for_loop.py"] exercise_preface: | ### Multiple erosion