From 7a92876df051791aa230eb664a5aaa666a22a212 Mon Sep 17 00:00:00 2001 From: Sangeetha Nandakumar <98574336+sangeethankumar@users.noreply.github.com> Date: Wed, 3 Jan 2024 14:17:25 +0100 Subject: [PATCH] Section 2 --- .../intro_to_calcium_imaging/tiff_file.ipynb | 455 +++++++++++++++++- 1 file changed, 437 insertions(+), 18 deletions(-) diff --git a/workshops/intro_to_calcium_imaging/tiff_file.ipynb b/workshops/intro_to_calcium_imaging/tiff_file.ipynb index c837931..41843c6 100644 --- a/workshops/intro_to_calcium_imaging/tiff_file.ipynb +++ b/workshops/intro_to_calcium_imaging/tiff_file.ipynb @@ -40,7 +40,7 @@ "source": [ "### Understanding the TIFF File structure \n", "\n", - "A single frame TIFF File has only one `page` or just one image. Here we will learn how to read and write single frame TIFF Files. " + "A single frame TIFF File has only one `page` or just one image. Here we will learn how to read and write single frame TIFF Files. Usually, it also comes with some metadata about the data. `tifffile` has methods to read and write TIFF Files and can handle metadata." ] }, { @@ -58,7 +58,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 3, @@ -96,7 +96,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 4, @@ -134,7 +134,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 5, @@ -172,7 +172,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 6, @@ -388,21 +388,18 @@ "\n", "```python\n", "# Step 1\n", - "with tiff.TiffFile('original_file.tif') as tif:\n", - " page = tif.pages[0].asarray() # Reading page/frame\n", - " description = json.loads(tif.pages[0].tags['ImageDescription'].value) # loading information already in ImageDescription into a dictionary called description \n", - " description['field_1'] = value_1 # adding new field\n", - " description['field_2'] = value_2 # adding new field \n", - " description['field_3'] = value_3 # adding new field \n", + "with tiff.TiffFile('data/page_1.tif') as tif:\n", + " page = tif.pages[0].asarray()\n", + " description = json.loads(tif.pages[0].tags['ImageDescription'].value)\n", + " description['page_num'] = 1\n", "\n", "# Step 2\n", "new_description = json.dumps(description)\n", - "with tiff.TiffWriter('page_1_add_meta.tif') as new_tif:\n", - " new_tif.save(page, description=new_description)\n", + "tiff.imsave('data/page_1_new.tif', page, description=new_description, metadata=None) \n", "```\n", "\n", "\n", - "**Example** Add `page_num` field to `page_1.tif` and save it as `page_1_new.tif`" + "**Example** Add `page_num` field to `page_1.tif` and save it as `page_1_new.tif` in the `data/` directory" ] }, { @@ -417,7 +414,7 @@ " description['page_num'] = 1\n", "\n", "new_description = json.dumps(description)\n", - "tiff.imsave('page_1_new.tif', page, description=new_description, metadata=None) \n" + "tiff.imsave('data/page_1_new.tif', page, description=new_description, metadata=None) \n" ] }, { @@ -439,7 +436,7 @@ " description['page_num'] = 2\n", "\n", "new_description = json.dumps(description)\n", - "tiff.imsave('page_2_new.tif', page, description=new_description, metadata=None) \n" + "tiff.imsave('data/page_2_new.tif', page, description=new_description, metadata=None) \n" ] }, { @@ -461,7 +458,7 @@ " description['page_num'] = 3\n", "\n", "new_description = json.dumps(description)\n", - "tiff.imsave('page_3_new.tif', page, description=new_description, metadata=None) \n" + "tiff.imsave('data/page_3_new.tif', page, description=new_description, metadata=None) \n" ] }, { @@ -483,7 +480,429 @@ " description['page_num'] = 4\n", "\n", "new_description = json.dumps(description)\n", - "tiff.imsave('page_4_new.tif', page, description=new_description, metadata=None) " + "tiff.imsave('data/page_4_new.tif', page, description=new_description, metadata=None) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Multi-frame TIFF File\n", + "\n", + "A single frame TIFF File cannot capture the dynamic changes in calcium levels within cells over time. Multi-frame images in calcium imaging are typically acquired as time-lapse sequences where each frame in a sequence represents a snapshot at a specific time point. Therefore, a multi-frame TIFF File has (as the name implies) multiple pages. Let us see how to handle such data in `Python` with the help of `tifffile`" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1000, 128, 128)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "frames = tiff.imread('data/data_endoscope.tif')\n", + "frames.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We read `data_endoscope.tif` file and the process is same as reading a single-frame TIFF File. We can see how many frames it has by `Numpy` method `.shape`. We see three numbers there meaning that it is a three dimensional data. \n", + "\n", + "1000: This is the number of frames or images in the TIFF file. It suggests that our file is a stack of 1000 separate images. In the context of calcium imaging, this usually corresponds to 1000 different time points at which the images were captured.\n", + "\n", + "128: the first 128 represents the width of each image/frame in pixels\n", + "\n", + "128: the first 128 represents the height of each image/frame in pixels\n", + "\n", + "Now let us see different ways of handling such data with `tifffile`\n", + "\n", + "**Example** Read only the first frame from `data/data_endoscope.tif`" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(128, 128)" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "frame_1 = tiff.imread('data/data_endoscope.tif', key=0)\n", + "frame_1.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read only the tenth frame from `data/data_endoscope.tif`" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(128, 128)" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "frame_10 = tiff.imread('data/data_endoscope.tif', key=9)\n", + "frame_10.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read only the last frame from `data/data_endoscope.tif`" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(128, 128)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "frame_1000 = tiff.imread('data/data_endoscope.tif', key=999)\n", + "frame_1000.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read only the 500th frame from `data/data_endoscope.tif`" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(128, 128)" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "frame_500 = tiff.imread('data/data_endoscope.tif', key=499)\n", + "frame_500.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Example** Read only 1st, 2nd, and 3rd frames" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 128, 128)" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "frames = tiff.imread('data/data_endoscope.tif', key=(0,1,2))\n", + "frames.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read only 10th, 500th, 1000th frames" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 128, 128)" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "frames = tiff.imread('data/data_endoscope.tif', key=(9,499,999))\n", + "frames.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Example** Read only the first ten frames " + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(10, 128, 128)" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "frames = tiff.imread('data/data_endoscope.tif', key=range(0,10))\n", + "frames.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read only last ten frames" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(10, 128, 128)" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "frames = tiff.imread('data/data_endoscope.tif', key=range(990,1000))\n", + "frames.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read last ten frames but in steps of two" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(5, 128, 128)" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "frames = tiff.imread('data/data_endoscope.tif', key=range(990,1000, 2))\n", + "frames.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Example** Add `frame_rate=10` to `ImageDescription` tag in all pages and save as new TIFF File" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'shape': [128, 128]}\n" + ] + } + ], + "source": [ + "with tiff.TiffFile('data/data_endoscope.tif') as in_tif:\n", + " frames = [page.asarray() for page in in_tif.pages]\n", + " description = json.loads(tif.pages[0].tags['ImageDescription'].value)\n", + " print(description)\n", + "\n", + "\n", + "frame_rate = 10\n", + "description['frame_rate'] = frame_rate\n", + "new_description = json.dumps(description)\n", + "\n", + "with tiff.TiffWriter('data/modified_tiff_file.tif') as out_tif:\n", + " for frame in frames:\n", + " out_tif.save(frame, description=new_description, metadata=None)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ImageWidth: 128\n", + "ImageLength: 128\n", + "BitsPerSample: 16\n", + "Compression: 1\n", + "PhotometricInterpretation: 1\n", + "ImageDescription: {\"shape\": [128, 128], \"frame_rate\": 10}\n", + "StripOffsets: (256,)\n", + "SamplesPerPixel: 1\n", + "RowsPerStrip: 128\n", + "StripByteCounts: (32768,)\n", + "XResolution: (1, 1)\n", + "YResolution: (1, 1)\n", + "ResolutionUnit: 1\n", + "Software: tifffile.py\n" + ] + } + ], + "source": [ + "with tiff.TiffFile('data/modified_tiff_file.tif') as tif:\n", + " page = tif.pages[0]\n", + " for tag in page.tags:\n", + " print(f\"{tag.name}: {tag.value}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add `decay_time=2.0` to `ImageDescription` of all frames and save `modified_tiff_file_2.tiff`" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'shape': [128, 128], 'frame_rate': 10}\n" + ] + } + ], + "source": [ + "with tiff.TiffFile('data/data_endoscope.tif') as in_tif:\n", + " frames = [page.asarray() for page in in_tif.pages]\n", + " description = json.loads(tif.pages[0].tags['ImageDescription'].value)\n", + " print(description)\n", + "\n", + "\n", + "decay_time = 10\n", + "description['decay_time'] = frame_rate\n", + "new_description = json.dumps(description)\n", + "\n", + "with tiff.TiffWriter('data/modified_tiff_file_2.tif') as out_tif:\n", + " for frame in frames:\n", + " out_tif.save(frame, description=new_description, metadata=None)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## OME data" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "None\n" + ] + } + ], + "source": [ + "with tiff.TiffFile('data/data_endoscope.tif') as tif:\n", + " ome_metadata = tif.ome_metadata\n" ] } ],