From 626be3b8a549a3afff9093c1f4628c6c7413da8e Mon Sep 17 00:00:00 2001 From: Jan Lebert Date: Mon, 6 May 2024 10:49:20 -0700 Subject: [PATCH] Update example data file names, update docs --- docs/tutorials/activation.ipynb | 5 +- docs/tutorials/apd.ipynb | 9 +-- docs/tutorials/basics.ipynb | 14 ++-- docs/tutorials/example_files.ipynb | 89 +++++++++++--------------- docs/tutorials/phase.ipynb | 9 +-- docs/tutorials/ratiometry.ipynb | 4 +- docs/tutorials/signal_extraction.ipynb | 11 ++-- optimap/__init__.py | 3 +- optimap/utils.py | 12 +++- 9 files changed, 70 insertions(+), 86 deletions(-) diff --git a/docs/tutorials/activation.ipynb b/docs/tutorials/activation.ipynb index b1d852f..a948f0d 100644 --- a/docs/tutorials/activation.ipynb +++ b/docs/tutorials/activation.ipynb @@ -78,10 +78,9 @@ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", - "filename = om.utils.retrieve_example_data('Example_01_Sinus_Rabbit_Basler.npy')\n", - "video = om.load_video(filename)\n", + "filename = om.download_example_data('Sinus_Rabbit_1.npy')\n", + "video = om.load_video(filename, frames=20)\n", "video = om.video.rotate_left(video)\n", - "video=video[:20] # only use first 20 frames\n", "\n", "# motion compensation and normalization\n", "video_warped = om.motion.motion_compensate(video, 5, ref_frame=0)\n", diff --git a/docs/tutorials/apd.ipynb b/docs/tutorials/apd.ipynb index b9b6367..adc11a9 100644 --- a/docs/tutorials/apd.ipynb +++ b/docs/tutorials/apd.ipynb @@ -64,7 +64,7 @@ "\n", "This tutorial discusses how to compute action potential durations (APDs) and APD maps from cardiac optical mapping data using ``optimap``. The routines can also be used to compute calcium transient durations (CaTDs) or CATD maps. In addition, we will also compute APD and CaTD histograms as well as upstroke timing and repolarization timing.\n", "\n", - "First, we will load a voltage- and calcium-sensitive optical mapping recording, see [Example Files](example_files.ipynb) for more information, and extract the two channels/videos from the recording:" + "First, we will load a voltage- and calcium-sensitive optical mapping recording, see [Example Data Files](example_files.ipynb) for more information, and extract the two channels/videos from the recording:" ] }, { @@ -77,9 +77,10 @@ "source": [ "import optimap as om\n", "\n", - "filename = om.utils.retrieve_example_data('optimap-example-file-03.npy')\n", - "video_voltage = om.load_video(filename, start_frame=0, step=2) # select the even frames\n", - "video_calcium = om.load_video(filename, start_frame=1, step=2) # select the odd frames\n", + "filename = om.download_example_data(\"Dualchannel_1.npy\")\n", + "\n", + "video_voltage = om.load_video(filename, start_frame=0, step=2) # even frames\n", + "video_calcium = om.load_video(filename, start_frame=1, step=2) # odd frames\n", "\n", "om.print_properties(video_voltage)\n", "om.print_properties(video_calcium)" diff --git a/docs/tutorials/basics.ipynb b/docs/tutorials/basics.ipynb index bb82974..39971f4 100644 --- a/docs/tutorials/basics.ipynb +++ b/docs/tutorials/basics.ipynb @@ -129,9 +129,9 @@ "metadata": {}, "outputs": [], "source": [ - "filepath = om.utils.retrieve_example_data('Example_02_VF_Rabbit_Di-4-ANEPPS_Basler_acA720-520um.npy')\n", + "filepath = om.download_example_data(\"VF_Rabbit_1.npy\")\n", "# alternative if you downloaded the file to your desktop\n", - "# filepath = 'Example_02_VF_Rabbit_Di-4-ANEPPS_Basler_acA720-520um.npy'\n", + "# filepath = 'VF_Rabbit_1.npy'\n", "video = om.load_video(filepath)\n", "\n", "om.print_properties(video)" @@ -186,7 +186,6 @@ }, "outputs": [], "source": [ - "video = video[:1000]\n", "render_ani_func(lambda: om.show_video(video, interval=15))" ] }, @@ -343,13 +342,8 @@ "outputs": [], "source": [ "# load pre-computed warped video to speed up docs build time\n", - "filepath = om.utils.retrieve_example_data('Example_02_VF_Rabbit_Di-4-ANEPPS_Basler_acA720-520um_warped.npy', silent=True)\n", - "video_warped = om.load_video(filepath, use_mmap=True)[:1000]\n", - "# fake tqdm progress bar\n", - "from tqdm import tqdm\n", - "from time import sleep\n", - "for _ in tqdm(range(1000), desc='Computing flows (CPU)'):\n", - " sleep(1/500.0)" + "filepath = om.download_example_data('VF_Rabbit_1_warped.npy', silent=True)\n", + "video_warped = om.load_video(filepath, use_mmap=True)" ] }, { diff --git a/docs/tutorials/example_files.ipynb b/docs/tutorials/example_files.ipynb index 5ec2b21..3d97287 100644 --- a/docs/tutorials/example_files.ipynb +++ b/docs/tutorials/example_files.ipynb @@ -12,42 +12,11 @@ "```" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-input", - "remove-output" - ] - }, - "outputs": [], - "source": [ - "# Code snippet for rendering animations in the docs\n", - "from IPython.display import HTML\n", - "import warnings\n", - "import matplotlib.pyplot as plt\n", - "\n", - "def render_ani_func(f):\n", - " om.utils.disable_interactive_backend_switching()\n", - " plt.switch_backend('Agg')\n", - " with warnings.catch_warnings():\n", - " warnings.simplefilter(\"ignore\")\n", - " ani = f()\n", - " ani.repeat = True\n", - " %matplotlib inline\n", - " om.utils.enable_interactive_backend_switching()\n", - "\n", - " vid = HTML(ani.to_html5_video(embed_limit=2**128))\n", - " plt.close('all')\n", - " return vid" - ] - }, { "cell_type": "markdown", "metadata": {}, "source": [ - "# Example Files\n", + "# Example Data Files\n", "\n", "``optimap`` provides several optical mapping example videos, which are used throughout the [Tutorials](https://optimap.readthedocs.io/en/latest/tutorials/). The example files can be used to test optimap or to develop your own analysis scripts. They can be downloaded directly within a script while using ``optimap``:" ] @@ -64,7 +33,7 @@ "source": [ "import optimap as om\n", "\n", - "filepath = om.utils.retrieve_example_data('optimap-example-file-01.npy')\n", + "filepath = om.download_example_data(\"VF_Rabbit_1.npy\")\n", "video = om.load_video(filepath)" ] }, @@ -72,20 +41,22 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "or, alternatively, be downloaded from [cardiacvision.ucsf.edu/optimap/](https://cardiacvision.ucsf.edu/optimap/) and stored on your harddrive. Please reference ``optimap`` if you use the example files in any publications." + "or, alternatively, be downloaded from [cardiacvision.ucsf.edu/optimap/](https://cardiacvision.ucsf.edu/optimap/). Please reference ``optimap`` if you use the example files in any publications.\n", + "\n", + "## Video Recordings" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "````{dropdown} Example File 1\n", + "````{dropdown} Rabbit_Sinus_1\n", ":closed:\n", "\n", - "Example file 1 is a voltage-sensitive optical mapping video recorded with a Basler acA720-520um camera. It shows an isolated rabbit heart during sinus rhythm. The heart was freely contracting. Excitation-contraction uncoupling agents, such as Blebbistatin, were not used during the experiment. \n", + "`Rabbit_Sinus_1` is a voltage-sensitive optical mapping video recorded with a Basler acA720-520um camera. It shows an isolated rabbit heart during sinus rhythm. The heart was freely contracting. Excitation-contraction uncoupling agents, such as Blebbistatin, were not used during the experiment. \n", "\n", "```python\n", - "filepath = om.utils.retrieve_example_data('optimap-example-file-01.npy')\n", + "filepath = om.download_example_data(\"Rabbit_Sinus_1.npy\")\n", "video = om.load_video(filepath)\n", "```\n", "\n", @@ -108,13 +79,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "````{dropdown} Example File 2\n", + "````{dropdown} VF_Rabbit_1\n", ":closed:\n", "\n", - "Example file 2 is a voltage-sensitive optical mapping video recorded with a Basler acA720-520um camera at 500 fps. It shows an isolated rabbit heart during ventricular fibrillation. The heart was freely contracting. Excitation-contraction uncoupling agents, such as Blebbistatin, were not used during the experiment. \n", + "`VF_Rabbit_1` is a voltage-sensitive optical mapping video recorded with a Basler acA720-520um camera at 500 fps. It shows an isolated rabbit heart during ventricular fibrillation. The heart was freely contracting. Excitation-contraction uncoupling agents, such as Blebbistatin, were not used during the experiment. \n", "\n", "```python\n", - "filepath = om.utils.retrieve_example_data('optimap-example-file-02.npy')\n", + "filepath = om.download_example_data(\"VF_Rabbit_1.npy\")\n", "video = om.load_video(filepath)\n", "```\n", "\n", @@ -129,7 +100,7 @@ "* Dye: Di-4-ANEPPS\n", "* Rhythm: Ventricular Fibrillation\n", "* Motion: Yes (no Blebbistatin)\n", - "* Dimensions: 1040 frames, 390x300 pixels\n", + "* Dimensions: 1000 frames, 390x300 pixels\n", "````" ] }, @@ -137,16 +108,27 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "````{dropdown} Example File 3\n", + "````{dropdown} Dualchannel_1\n", ":closed:\n", "\n", - "Example file 3 is a voltage- and calcium-sensitive optical mapping video. It shows action potential and calcium waves in an isolated rabbit heart during pacing. The heart was uncoupled using Blebbistatin.\n", + "`Dualchannel_1` contains a dual-channel voltage- and calcium-sensitive optical mapping video. It shows action potential and calcium waves in an isolated rabbit heart during pacing. The heart was uncoupled using Blebbistatin.\n", "\n", "```python\n", - "filepath = om.utils.retrieve_example_data('optimap-example-file-03.npy')\n", - "video = om.load_video(filepath)\n", + "filepath = om.download_example_data(\"Dualchannel_1.zip\")\n", + "filepath /= \"Burst pacing bleb s1 60ms.rsh\" # path to recording in unzipped folder\n", + "\n", + "video_voltage = om.load_video(filename, start_frame=0, step=2) # select the even frames\n", + "video_calcium = om.load_video(filename, start_frame=1, step=2) # select the odd frames\n", + "\n", + "metadata = om.load_metadata(filepath)\n", + "print(metadata)\n", + "\n", + "# pacing section of the recording also available as separate file:\n", + "filepath = om.download_example_data(\"Dualchannel_1.npy\")\n", + "video_voltage = om.load_video(filepath, start_frame=0, step=2) # select the even frames\n", + "video_calcium = om.load_video(filepath, start_frame=1, step=2) # select the odd frames\n", "```\n", - "The example video file was originally recorded as a dual-channel video and was converted to a .npy file using ``optimap``. The even frames correspond to the voltage-sensitive and the odd frames to the calcium-sensitive video.\n", + "`Dualchannel_1.zip` contains the original whole SciMedia MiCAM ULTIMA recording, `Dualchannel_1.npy` contains only the pacing section of the recording and is rotated by 90 degrees. The even frames correspond to the voltage-sensitive and the odd frames to the calcium-sensitive video.\n", "\n", "* Date: August 17, 2021\n", "* Experimenters: Hao Zhang, Jeff Olgin\n", @@ -155,9 +137,9 @@ "* Imaging Speed: 1000 fps\n", "* Mode: voltage- and calcium-sensitive (dual channel)\n", "* Dye: \n", - "* Rhythm: Sinus\n", + "* Rhythm: Pacing\n", "* Motion: No (with Blebbistatin)\n", - "* Dimensions: 2696 frames, 100x100 pixels\n", + "* Dimensions: 2x 2048 frames (SciMedia MiCAM ULTIMA) or 2x 1348 frames (`.npy` file), 100x100 pixels\n", "\n", "````" ] @@ -166,14 +148,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "````{dropdown} Example File 4\n", + "````{dropdown} Ratiometry_1\n", ":closed:\n", "\n", - "Example file 4 is a ratiometric voltage-sensitive optical mapping video showing ventricular pacing in an isolated rabbit heart. The heart was freely contracting. Excitation-contraction uncoupling agents, such as Blebbistatin, were not used during the experiment. \n", + "`Ratiometry_1` is a ratiometric voltage-sensitive optical mapping video showing ventricular pacing in an isolated rabbit heart. The heart was freely contracting. Excitation-contraction uncoupling agents, such as Blebbistatin, were not used during the experiment. \n", "\n", "```python\n", - "filepath = om.utils.retrieve_example_data('optimap-example-file-04.npy')\n", + "filepath = om.download_example_data(\"Ratiometry_1.npy\")\n", "video = om.load_video(filepath)\n", + "\n", + "odd_frames = video[::2]\n", + "even_frames = video[1::2]\n", "```\n", "The example video file was originally recorded as a dual-channel video and was converted to a .npy file using ``optimap``. The even and odd frames were excited with blue and green light (or the other way around), respectively.\n", "\n", @@ -188,7 +173,7 @@ "* Motion: Yes (no Blebbistatin)\n", "* Dimensions: 1200 frames, 128x128 pixels\n", "\n", - "see [{cite:t}`Kappadan2020`] for details.\n", + "see {cite:t}`Kappadan2020` for details.\n", "````" ] } diff --git a/docs/tutorials/phase.ipynb b/docs/tutorials/phase.ipynb index f0717b3..6cf4d3e 100644 --- a/docs/tutorials/phase.ipynb +++ b/docs/tutorials/phase.ipynb @@ -76,17 +76,14 @@ "import optimap as om\n", "import numpy as np\n", "\n", - "filepath = om.utils.retrieve_example_data('optimap-example-file-02.npy')\n", - "# alterantively set filepath = '/folder_on_your_computer/optimap-example-file-02.npy'\n", - "video = om.load_video(filepath)[:500]\n", + "filepath = om.download_example_data('VF_Rabbit_1.npy')\n", + "video = om.load_video(filepath, frames=500)\n", "video_warped = om.motion_compensate(video,\n", " contrast_kernel=5,\n", " presmooth_spatial=1,\n", " presmooth_temporal=1)\n", "\n", - "video_warped_normalized = om.video.normalize_pixelwise_slidingwindow(video_warped, window_size=60)\n", - "\n", - "#del video, video_warped" + "video_warped_normalized = om.video.normalize_pixelwise_slidingwindow(video_warped, window_size=60)" ] }, { diff --git a/docs/tutorials/ratiometry.ipynb b/docs/tutorials/ratiometry.ipynb index 0ad6f84..f6de4ea 100644 --- a/docs/tutorials/ratiometry.ipynb +++ b/docs/tutorials/ratiometry.ipynb @@ -70,7 +70,7 @@ "source": [ "import optimap as om\n", "\n", - "filename = om.utils.retrieve_example_data('Example_05_Ratiometry.npy')\n", + "filename = om.download_example_data(\"Ratiometry_1.npy\")\n", "video_blue = om.load_video(filename, start_frame=0, step=2)\n", "video_green = om.load_video(filename, start_frame=1, step=2)\n", "\n", @@ -394,7 +394,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.9" + "version": "3.12.2" }, "orig_nbformat": 4 }, diff --git a/docs/tutorials/signal_extraction.ipynb b/docs/tutorials/signal_extraction.ipynb index 571b566..b0198b5 100644 --- a/docs/tutorials/signal_extraction.ipynb +++ b/docs/tutorials/signal_extraction.ipynb @@ -78,8 +78,7 @@ "import optimap as om\n", "import numpy as np\n", "\n", - "filepath = om.utils.retrieve_example_data('Example_02_VF_Rabbit_Di-4-ANEPPS_Basler_acA720-520um.npy')\n", - "# alterantively set filepath = '/folder_on_your_computer/Example_02_VF_Rabbit_Di-4-ANEPPS_Basler_acA720-520um.npy'\n", + "filepath = om.download_example_data('VF_Rabbit_1.npy')\n", "video = om.load_video(filepath)\n", "video_warped = om.motion_compensate(video,\n", " contrast_kernel=5,\n", @@ -103,10 +102,10 @@ "import optimap as om\n", "import numpy as np\n", "\n", - "filepath = om.utils.retrieve_example_data('Example_02_VF_Rabbit_Di-4-ANEPPS_Basler_acA720-520um.npy')\n", - "video = om.load_video(filepath, use_mmap=True)[:500]\n", - "filepath = om.utils.retrieve_example_data('Example_02_VF_Rabbit_Di-4-ANEPPS_Basler_acA720-520um_warped.npy', silent=True)\n", - "video_warped = om.load_video(filepath, use_mmap=True)[:500]\n", + "filepath = om.download_example_data('VF_Rabbit_1.npy')\n", + "video = om.load_video(filepath, use_mmap=True, frames=500)\n", + "filepath = om.download_example_data('VF_Rabbit_1_warped.npy', silent=True)\n", + "video_warped = om.load_video(filepath, use_mmap=True, frames=500)\n", "render_ani_func(lambda: om.show_video(video_warped, title=\"recording without motion\", skip_frame=1, interval=20))" ] }, diff --git a/optimap/__init__.py b/optimap/__init__.py index 9bb7765..3f6c6ed 100644 --- a/optimap/__init__.py +++ b/optimap/__init__.py @@ -36,7 +36,7 @@ show_positions, show_traces, ) -from .utils import is_verbose, print_bar, print_properties, set_verbose +from .utils import is_verbose, print_bar, print_properties, set_verbose, download_example_data from .video import ( export_video, load_metadata, @@ -103,6 +103,7 @@ "compute_phase", "compute_activation_map", + "download_example_data", "set_verbose", "is_verbose", "print_bar", diff --git a/optimap/utils.py b/optimap/utils.py index 3335b45..9a95efa 100644 --- a/optimap/utils.py +++ b/optimap/utils.py @@ -13,6 +13,7 @@ import functools import urllib.parse import warnings +from pathlib import Path import matplotlib as mpl import matplotlib.pyplot as plt @@ -215,11 +216,11 @@ def wrapper(*args, **kwargs): return wrapper @deprecated("Use download_example_data instead") -def retrieve_example_data(name, directory="./example_data", silent=False): +def retrieve_example_data(name, directory="./optimap_example_data", silent=False): return download_example_data(name, directory=directory, silent=silent) -def download_example_data(name, directory="./example_data", silent=False): +def download_example_data(name, directory="./optimap_example_data", silent=False): """Download example data if not already present. Parameters @@ -255,13 +256,20 @@ def download_example_data(name, directory="./example_data", silent=False): # We use .webm as dummy extension to upload the files, and rename them after download. url = f"https://cardiacvision.ucsf.edu/sites/g/files/tkssra6821/f/{remote_path}_.webm" + is_zip = Path(name).suffix == ".zip" path = pooch.retrieve( url=url, known_hash=known_hash, fname=name, path=directory, + processor=pooch.Unzip(extract_dir=Path(name).stem) if is_zip else None, ) if silent: pooch.get_logger().setLevel(silent) + + if is_zip: + path = Path(path[0]).parent + else: + path = Path(path) return path