diff --git a/notebooks/SeqFISH.ipynb b/notebooks/SeqFISH.ipynb index 655cb8a1e..3f329fa6d 100644 --- a/notebooks/SeqFISH.ipynb +++ b/notebooks/SeqFISH.ipynb @@ -2,18 +2,19 @@ "cells": [ { "cell_type": "markdown", + "id": "2f3df2ba", "metadata": {}, "source": [ - "# Starfish SeqFISH Work-in-progress Processing Example" + "## seqFISH Processing Example" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, + "id": "41fd344b", "metadata": {}, "outputs": [], "source": [ - "%gui qt\n", "\n", "import os\n", "from copy import deepcopy\n", @@ -28,296 +29,226 @@ "\n", "import starfish\n", "import starfish.data\n", - "from starfish.types import Axes, Levels, TraceBuildingStrategies" + "from starfish.types import Axes, Levels, TraceBuildingStrategies\n", + "\n", + "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", + "id": "c223f116", "metadata": {}, "source": [ - "Select data for a single field of view." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "exp = starfish.data.SeqFISH(use_test_data=True)" + "### Load Image" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, + "id": "90d79266", "metadata": {}, "outputs": [], "source": [ + "exp = starfish.data.SeqFISH(use_test_data=True)\n", "img = exp['fov_000'].get_image('primary')" ] }, { "cell_type": "markdown", + "id": "99516486", "metadata": {}, "source": [ - "The first step in SeqFISH is to do some rough registration. For this data, the rough registration has been done for us by the authors, so it is omitted from this notebook." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Remove image background" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To remove image background, use a White Tophat filter, which measures the background with a rolling disk morphological element and subtracts it from the image." + "### Processing" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, + "id": "9b417793", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1740/1740 [00:02<00:00, 622.08it/s]\n" + ] + } + ], "source": [ - "from skimage.morphology import opening, dilation, disk\n", - "from functools import partial" + "# Remove cellular autofluorescence w/ gaussian high-pass filter\n", + "ghp = starfish.image.Filter.GaussianHighPass(sigma=3)\n", + "ghp.run(img, verbose=False, in_place=True)\n", + "\n", + "# Increase resolution by deconvolving w/ point spread function\n", + "dpsf = starfish.image.Filter.DeconvolvePSF(num_iter=15, sigma=3)\n", + "dpsf.run(img, verbose=False, in_place=True)\n", + "\n", + "# Scale intensities in each volume and clip all but high intensity pixels\n", + "clip = starfish.image.Filter.Clip(p_min=90, p_max=99.9, is_volume=True, level_method=Levels.SCALE_BY_CHUNK)\n", + "scaled = clip.run(img, in_place=False)" ] }, { "cell_type": "markdown", + "id": "4577edcc", "metadata": {}, "source": [ - "If desired, the background that is being subtracted can be visualized" + "### Spot Finding" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, + "id": "98cd3960", "metadata": {}, "outputs": [], "source": [ - "opening = partial(opening, selem=disk(3))\n", + "threshold = 0.1\n", "\n", - "background = img.apply(\n", - " opening,\n", - " group_by={Axes.ROUND, Axes.CH, Axes.ZPLANE}, verbose=False, in_place=False\n", - ")\n", + "bd = starfish.spots.FindSpots.BlobDetector(\n", + " min_sigma=(1, 1, 1),\n", + " max_sigma=(5, 5, 5),\n", + " num_sigma=10,\n", + " threshold=threshold)\n", "\n", - "starfish.display(background)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "wth = starfish.image.Filter.WhiteTophat(masking_radius=3)\n", - "background_corrected = wth.run(img, in_place=False)\n", - "starfish.display(background_corrected)" + "spots = bd.run(scaled)" ] }, { "cell_type": "markdown", + "id": "0c4fcc39", "metadata": {}, "source": [ - "## Scale images to equalize spot intensities across channels\n", + "### Decoding\n", "\n", - "The number of peaks are not uniform across rounds and channels, which prevents histogram matching across channels. Instead, a percentile value is identified and set as the maximum across channels, and the dynamic range is extended to equalize the channel intensities" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "clip = starfish.image.Filter.Clip(p_max=99.9, is_volume=True, level_method=Levels.SCALE_BY_CHUNK)\n", - "scaled = clip.run(background_corrected, in_place=False)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "starfish.display(scaled)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Remove residual background\n", + "Comparison between using PerRoundMaxChannel w/ NEAREST_NEIGHBOR TraceBuildingStrategies and the three different accuracy modes of the CheckAll decoder.\n", "\n", - "The background is fairly uniformly present below intensity=0.5. However, starfish's clip method currently only supports percentiles. To solve this problem, the intensities can be directly edited in the underlying numpy array." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from copy import deepcopy\n", - "clipped = deepcopy(scaled)\n", - "clipped.xarray.values[clipped.xarray.values < 0.7] = 0" + "Runs each decoder for three different search radii parameters (1, 2, and 3) and creates a bar plot showing the total number of decoded mRNA targets found by each method. For the CheckAll decoder columns, the number of non-error corrected barcodes is denoted by a black line in the bar while the full height of the bar shows the combined number of error-corrected and non-error-corrected barcodes. \n", + "\n" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "starfish.display(clipped)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, + "execution_count": 10, + "id": "2e87c0c4", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/png": "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RwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIbWJTxW1Xmqavf1WBYAAACbz5rDY1XdtKqeVVXnmZl2/qr6aJJfJDmqqp67LSoJAADAxlqk5fFhSe7YWjt6ZtpzktwgyXeS/DLJw6vqLutYPwAAADaBRcLjlZN8YulOVZ0tyZ2SfKC1dtkkl0vygyQPWtcaAgAAsOEWCY/nT/LjmfvXSnLWJAcmSWvtuCTvSg+RAAAA7EAWCY8nJjnbzP0bJGlJPjYz7VdJ9lyHegEAALCJLBIeD09yk5n7ByT5dmvtRzPTLpY+eA4AAAA7kEXC46uSXLGqPlNVH09yxSSvnytzpSTfXK/KAQAAsDksEh7/Pckbklw9yfXSj2/856WZVfUn6YHyoHWsHwAAAJvArmst2Fo7Ock9qupB/W47bq7IT5NcNb17KwAAADuQRVoekySttV8tExzTWvtFku8luf96VAwA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AACAjbZQeEyS1trBSQ7eBnUBAABgk1pkwBwAAAB2Umtpedyjqi6+yEJba9/fwvoAAACwCa0lPD58uqxVW+NyAQAAOINYS8j7VZJjtnE9AAAA2MTWEh6f11p7yjavCQAAAJuWAXMAAAAYEh4BAAAYEh4BAAAYEh4BAAAYWnXAnNaacAkAAICWRwAAAMaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIaERwAAAIZ23egKAKyk/uOZG10F2O5+udEVAIAVaHkEAABgSHgEAABgSHgEAABg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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ - "## Detect Spots\n", + "# Set the number of cpu cores to use in parallel for the CheckAll decoder. This significantly cuts down on run time.\n", + "n_cpus = 24\n", "\n", - "Detect spots with a local search blob detector that identifies spots in all rounds and channels and matches them using a local search method. The local search starts in an anchor channel (default ch=1) and identifies the nearest spot in all subsequent imaging rounds." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "threshold = 0.5\n", + "# Run each decoder for different search radius values\n", + "for radius in [2, 3, 4]:\n", + " \n", + " # Decode using PerRoundMaxChannel NEAREST_NEIGHBOR method\n", + " decoder = starfish.spots.DecodeSpots.PerRoundMaxChannel(\n", + " codebook=exp.codebook,\n", + " search_radius=radius,\n", + " trace_building_strategy=TraceBuildingStrategies.NEAREST_NEIGHBOR)\n", "\n", - "bd = starfish.spots.FindSpots.BlobDetector(\n", - " min_sigma=(1.5, 1.5, 1.5),\n", - " max_sigma=(8, 8, 8),\n", - " num_sigma=10,\n", - " threshold=threshold)\n", + " decoded_prmc = decoder.run(spots=spots)\n", + " decoded_prmc = decoded_prmc[decoded_prmc['passes_thresholds']]\n", "\n", - "spots = bd.run(clipped)\n", - "decoder = starfish.spots.DecodeSpots.PerRoundMaxChannel(\n", - " codebook=exp.codebook,\n", - " search_radius=7,\n", - " trace_building_strategy=TraceBuildingStrategies.NEAREST_NEIGHBOR)\n", + " # Decode using high accuracy CheckAll method\n", + " decoder = starfish.spots.DecodeSpots.CheckAll(codebook=exp.codebook,\n", + " search_radius=radius,\n", + " error_rounds=1,\n", + " mode='high')\n", "\n", - "decoded = decoder.run(spots=spots)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "starfish.display(clipped, decoded)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Based on visual inspection, it looks like the spot correspondence across rounds isn't being detected well. Try the PixelSpotDecoder." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "glp = starfish.image.Filter.GaussianLowPass(sigma=(0.3, 1, 1), is_volume=True)\n", - "blurred = glp.run(clipped)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "psd = starfish.spots.DetectPixels.PixelSpotDecoder(\n", - " codebook=exp.codebook, metric='euclidean', distance_threshold=0.5,\n", - " magnitude_threshold=0.1, min_area=7, max_area=50,\n", - ")\n", - "pixel_decoded, ccdr = psd.run(blurred)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# look at the label image in napari\n", - "label_image = starfish.ImageStack.from_numpy(np.reshape(ccdr.decoded_image, (1, 1, 29, 280, 280)))\n", - "starfish.display(label_image)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compare the number of spots being detected by the two spot finders" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\"pixel_decoder spots detected\", int(np.sum(pixel_decoded['target'] != 'nan')))\n", - "print(\"local search spot detector spots detected\", int(np.sum(decoded['target'] != 'nan')))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Report the correlation between the two methods" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from scipy.stats import pearsonr\n", + " checkall_high = decoder.run(spots=spots, n_processes=n_cpus)\n", + "\n", + " # Decode using medium accuracy CheckAll method\n", + " decoder = starfish.spots.DecodeSpots.CheckAll(codebook=exp.codebook,\n", + " search_radius=radius,\n", + " error_rounds=1,\n", + " mode='med')\n", + "\n", + " checkall_med = decoder.run(spots=spots, n_processes=n_cpus)\n", + "\n", + " # Decode using low accuracy CheckAll method\n", + " decoder = starfish.spots.DecodeSpots.CheckAll(codebook=exp.codebook,\n", + " search_radius=radius,\n", + " error_rounds=1,\n", + " mode='low')\n", + "\n", + " checkall_low = decoder.run(spots=spots, n_processes=n_cpus)\n", "\n", - "# get the total counts for each gene from each spot detector\n", - "pixel_decoded_gene_counts = pd.Series(*np.unique(pixel_decoded['target'], return_counts=True)[::-1])\n", - "decoded_gene_counts = pd.Series(*np.unique(decoded['target'], return_counts=True)[::-1])\n", + " # Plot total number of barcodes from each method (black line shows number of full barcodes while bar height is\n", + " # the combined number of both error-corrected and non-error-corrected)\n", + " fig, axes = plt.subplots(1, 1, figsize=(15,15))\n", "\n", - "# get the genes that are detected by both spot finders\n", - "codetected = pixel_decoded_gene_counts.index.intersection(decoded_gene_counts.index).drop('nan')\n", + " labels = ['PerRoundMaxChannel', 'CheckAll (high)', 'CheckAll (med)', 'CheckAll (low)']\n", + " axes.bar([1], len(decoded_prmc), color=(0/256, 119/256, 187/256), width=1, label='PerRoundMaxChannel')\n", + " axes.plot([0.5, 1.5], [len(decoded_prmc), len(decoded_prmc)], color='black', linewidth=3)\n", + " axes.bar([2], len(checkall_high), color=(0/256, 153/256, 136/256), width=1, label='CheckAll (high)')\n", + " axes.plot([1.5, 2.5],\n", + " [len(checkall_high[checkall_high['rounds_used'] == 5]), len(checkall_high[checkall_high['rounds_used'] == 5])],\n", + " color='black', linewidth=3)\n", + " axes.bar([3], len(checkall_med), color=(238/256, 119/256, 51/256), width=1, label='CheckAll (med)')\n", + " axes.plot([2.5, 3.5],\n", + " [len(checkall_med[checkall_med['rounds_used'] == 5]), len(checkall_med[checkall_med['rounds_used'] == 5])],\n", + " color='black', linewidth=3)\n", + " axes.bar([4], len(checkall_low), color=(238/256, 51/256, 119/256), width=1, label='CheckAll (low)')\n", + " axes.plot([3.5, 4.5],\n", + " [len(checkall_low[checkall_low['rounds_used'] == 5]), len(checkall_low[checkall_low['rounds_used'] == 5])],\n", + " color='black', linewidth=3)\n", "\n", - "# report the correlation\n", - "pearsonr(pixel_decoded_gene_counts[codetected], decoded_gene_counts[codetected])" + " axes.set_xticks(range(1,5))\n", + " axes.set_xticklabels(labels, size=16)\n", + " axes.set_yticks(range(0, int(len(checkall_low)+len(checkall_low)/10+1), 100))\n", + " axes.set_yticklabels(range(0, int(len(checkall_low)+len(checkall_low)/10+1), 100), size=16)\n", + " axes.set_ylim(0, len(checkall_low)+len(checkall_low)/10)\n", + " axes.set_xlabel('Decoding Method', size=20)\n", + " axes.set_ylabel('Total Decoded mRNAs', size=20)\n", + " axes.set_title(f'Search Radius = {radius}', size=30)" ] } ], "metadata": { "kernelspec": { - "display_name": "starfish", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "starfish" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -329,9 +260,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.9.13" } }, "nbformat": 4, - "nbformat_minor": 2 -} \ No newline at end of file + "nbformat_minor": 5 +} diff --git a/starfish/core/morphology/binary_mask/binary_mask.py b/starfish/core/morphology/binary_mask/binary_mask.py index 79d75d688..d41be0e54 100644 --- a/starfish/core/morphology/binary_mask/binary_mask.py +++ b/starfish/core/morphology/binary_mask/binary_mask.py @@ -355,13 +355,28 @@ def from_external_labeled_image(cls, path_to_labeled_image: Union[str, Path], # Load the label image generated from another program label_image = io.imread(path_to_labeled_image) - # Get the physical ticks from the original dapi image - physical_ticks = {Coordinates.Y: original_image.xarray.yc.values, - Coordinates.X: original_image.xarray.xc.values} + # Fixes dimension order. Tiff files saved with skimage.io.imsave and tifffile.imsave will + # have different dimension order when read in. + if len(label_image.shape) == 3 and label_image.shape[0] > label_image.shape[-1]: + label_image = np.transpose(label_image, [2, 0, 1]) + + if len(label_image.shape) == 3: + # Get the physical ticks from the original dapi image + physical_ticks = {Coordinates.Y: original_image.xarray.yc.values, + Coordinates.X: original_image.xarray.xc.values, + Coordinates.Z: original_image.xarray.zc.values} + + # Get the pixel values from the original dapi image + pixel_coords = {Axes.Y: original_image.xarray.y.values, + Axes.X: original_image.xarray.x.values, + Axes.ZPLANE: original_image.xarray.z.values} + else: + physical_ticks = {Coordinates.Y: original_image.xarray.yc.values, + Coordinates.X: original_image.xarray.xc.values} - # Get the pixel values from the original dapi image - pixel_coords = {Axes.Y: original_image.xarray.y.values, - Axes.X: original_image.xarray.x.values} + # Get the pixel values from the original dapi image + pixel_coords = {Axes.Y: original_image.xarray.y.values, + Axes.X: original_image.xarray.x.values} # Create the label image label_im = LabelImage.from_label_array_and_ticks( diff --git a/starfish/core/spots/DecodeSpots/check_all_decoder.py b/starfish/core/spots/DecodeSpots/check_all_decoder.py index 77a3c8a05..847279e5b 100644 --- a/starfish/core/spots/DecodeSpots/check_all_decoder.py +++ b/starfish/core/spots/DecodeSpots/check_all_decoder.py @@ -325,8 +325,8 @@ def run(self, # Adds spot_codes column to roundData roundData = buildBarcodes(roundData, neighborDict, - currentRoundOmitNum, channelDict, - strictness, r, numJobs) + currentRoundOmitNum, strictness, r, + numJobs) # When strictness is positive the filter-first methods is used # and distanceFilter is run first on all the potential barcodes @@ -400,7 +400,12 @@ def run(self, # create empty IntensityTable filled with np.nan data = np.full((len(allCodes), len(channels), len(rounds)), fill_value=np.nan) dims = (Features.AXIS, Axes.CH.value, Axes.ROUND.value) - centers = allCodes['center'] + + if len(allCodes) == 0: + centers = [] + else: + centers = allCodes['center'] + coords: Mapping[Hashable, Tuple[str, Any]] = { Features.SPOT_RADIUS: (Features.AXIS, np.full(len(allCodes), 1)), Axes.ZPLANE.value: (Features.AXIS, np.asarray([round(c[0]) for c in centers])), @@ -413,28 +418,37 @@ def run(self, } int_table = IntensityTable(data=data, dims=dims, coords=coords) - # Fill in data values - table_codes = [] - for i in range(len(allCodes)): - code = [] - # ints = allCodes.loc[i, 'intensities'] - for j, ch in enumerate(allCodes.loc[i, 'best_barcodes']): - # If a round is not used, row will be all zeros - code.append(np.asarray([0 if k != ch - 1 else 1 for k in range(len(channels))])) - table_codes.append(np.asarray(code).T) - int_table.values = np.asarray(table_codes) - int_table = transfer_physical_coords_to_intensity_table(intensity_table=int_table, - spots=spots) - - # Validate results are correct shape - self.codebook._validate_decode_intensity_input_matches_codebook_shape(int_table) - - # Create DecodedIntensityTable - result = DecodedIntensityTable.from_intensity_table( - int_table, - targets=(Features.AXIS, allCodes['targets'].astype('U')), - distances=(Features.AXIS, allCodes["distance"]), - passes_threshold=(Features.AXIS, np.full(len(allCodes), True)), - rounds_used=(Features.AXIS, allCodes['rounds_used'])) + # If no targets found returns empty DecodedIntensityTable + if len(allCodes) > 0: + # Fill in data values + table_codes = [] + for i in range(len(allCodes)): + code = [] + # ints = allCodes.loc[i, 'intensities'] + for j, ch in enumerate(allCodes.loc[i, 'best_barcodes']): + # If a round is not used, row will be all zeros + code.append(np.asarray([0 if k != ch - 1 else 1 for k in range(len(channels))])) + table_codes.append(np.asarray(code).T) + int_table.values = np.asarray(table_codes) + int_table = transfer_physical_coords_to_intensity_table(intensity_table=int_table, + spots=spots) + + # Validate results are correct shape + self.codebook._validate_decode_intensity_input_matches_codebook_shape(int_table) + + # Create DecodedIntensityTable + result = DecodedIntensityTable.from_intensity_table( + int_table, + targets=(Features.AXIS, allCodes['targets'].astype('U')), + distances=(Features.AXIS, allCodes["distance"]), + passes_threshold=(Features.AXIS, np.full(len(allCodes), True)), + rounds_used=(Features.AXIS, allCodes['rounds_used'])) + else: + result = DecodedIntensityTable.from_intensity_table( + int_table, + targets=(Features.AXIS, np.array([])), + distances=(Features.AXIS, np.array([])), + passes_threshold=(Features.AXIS, np.array([])), + rounds_used=(Features.AXIS, np.array([]))) return result diff --git a/starfish/core/spots/DecodeSpots/check_all_funcs.py b/starfish/core/spots/DecodeSpots/check_all_funcs.py index 3d36e42de..ff3bdda20 100644 --- a/starfish/core/spots/DecodeSpots/check_all_funcs.py +++ b/starfish/core/spots/DecodeSpots/check_all_funcs.py @@ -131,7 +131,7 @@ def createRefDicts(spotTables: dict, numJobs: int) -> tuple: spotIntensities[r][0] = 0 # Create normalized intensity dictionary - spotQualDict = spotQuality(spotTables, spotCoords, spotIntensities, channelDict, numJobs) + spotQualDict = spotQuality(spotTables, spotIntensities, numJobs) return channelDict, spotCoords, spotIntensities, spotQualDict @@ -182,69 +182,8 @@ def decodeSpots(compressed: list, roundNum: int) -> list: for j in range(len(idxs))] return decompressed -def spotQualityFunc(spots: list, - spotCoords: dict, - spotIntensities: dict, - spotTables: dict, - channelDict: dict, - r: int) -> list: - - ''' - Helper function for spotQuality to run in parallel - Parameters - ---------- - spots : list - List of spot IDs in the current round to calculate the normalized intensity of - spotCoords : dict - Spot ID to spatial coordinate dictionary - spotIntensities : dict - Spot ID to raw intensity dictionary - spotTables : dict - Dictionary containing spot info tables - channelDict : dict - Spot ID to channel label dictionary - r : int - Current round - Returns - ------- - list : list of normalized spot intensities of the input spot IDs - ''' - - # Find spots in the same neighborhood (same channel and z slice and less than 100 pixels away - # in either x or y direction) - neighborhood = 100 - quals = [] - for i, spot in enumerate(spots): - z, y, x = spotCoords[r][spot] - ch = channelDict[r][spot] - yMin = y - neighborhood if y - neighborhood >= 0 else 0 - yMax = y + neighborhood if y + neighborhood <= 2048 else 2048 - xMin = x - neighborhood if x - neighborhood >= 0 else 0 - xMax = x + neighborhood if x + neighborhood <= 2048 else 2048 - neighborInts = spotTables[r][(spotTables[r]['c'] == ch) - & (spotTables[r]['z'] == z) - & (spotTables[r]['y'] >= yMin) - & (spotTables[r]['y'] < yMax) - & (spotTables[r]['x'] >= xMin) - & (spotTables[r]['x'] < xMax)]['intensity'] - # If no neighbors drop requirement that they be within 100 pixels of each other - if len(neighborInts) == 1: - neighborInts = spotTables[r][(spotTables[r]['c'] == ch) - & (spotTables[r]['z'] == z)]['intensity'] - # If still no neighbors drop requirement that they be on the same z slice - if len(neighborInts) == 1: - neighborInts = spotTables[r][(spotTables[r]['c'] == ch)]['intensity'] - # Calculate the l2 norm of the neighbor's intensities and divide the spot's intensity by - # this value to get it's normalized intensity value - norm = np.linalg.norm(neighborInts) - quals.append(spotIntensities[r][spot] / norm) - - return quals - def spotQuality(spotTables: dict, - spotCoords: dict, spotIntensities: dict, - channelDict: dict, numJobs: int) -> dict: ''' @@ -255,12 +194,8 @@ def spotQuality(spotTables: dict, ---------- spotTables : dict Dictionary containing spot info tables - spotCoords : dict - Spot ID to spatial coordinate dictionary spotIntensities : dict Spot ID to raw intensity dictionary - channelDict : dict - Spot ID to channel label dictionary numJobs : int Number of CPU threads to use in parallel Returns @@ -269,33 +204,37 @@ def spotQuality(spotTables: dict, ''' # Calculate normalize spot intensities for each spot in each round - spotQuals = {} # type: dict + spotQuals = defaultdict(dict) # type: dict + neigborhood = 100 for r in range(len(spotTables)): - roundSpots = spotTables[r]['spot_id'] - spotQuals[r] = {} - - # Calculates index ranges to chunk data by - ranges = [0] - for i in range(1, numJobs): - ranges.append(round((len(roundSpots) / numJobs) * i)) - ranges.append(len(roundSpots)) - chunkedSpots = [roundSpots[ranges[i]:ranges[i + 1]] for i in range(len(ranges[:-1]))] - - # Run in parallel - with ProcessPoolExecutor() as pool: - part = partial(spotQualityFunc, spotCoords=spotCoords, spotIntensities=spotIntensities, - spotTables=spotTables, channelDict=channelDict, r=r) - poolMap = pool.map(part, [subSpots for subSpots in chunkedSpots]) - results = [x for x in poolMap] - - # Extract results - for spot, qual in zip(roundSpots, list(chain(*results))): - spotQuals[r][spot] = qual + all_ch_all_z = spotTables[r][['z', 'y', 'x', 'spot_id', 'intensity']] + for ch in sorted(set(spotTables[r]['c'])): + one_ch_all_z = spotTables[r][spotTables[r]['c'] == ch][['z', 'y', 'x', 'spot_id', + 'intensity']] + for z in sorted(set(spotTables[r]['z'])): + one_ch_one_z = spotTables[r][(spotTables[r]['c'] == ch) + & (spotTables[r]['z'] == z)][['z', 'y', 'x', 'spot_id', + 'intensity']] + slice_ids = one_ch_one_z['spot_id'].to_list() + tree = cKDTree(one_ch_one_z[['z', 'y', 'x']]) + res = tree.query_ball_point(one_ch_one_z[['z', 'y', 'x']], neigborhood, + workers=numJobs) + for i, spot_id in enumerate(one_ch_one_z['spot_id']): + if len(res[i]) > 1: + neighbor_ids = [slice_ids[x] for x in res[i]] + intensities = [spotIntensities[r][neighbor_id] for neighbor_id in + neighbor_ids] + elif len(one_ch_all_z) > 1: + intensities = one_ch_all_z['intensity'] + else: + intensities = all_ch_all_z['intensity'] + + norm = np.linalg.norm(intensities) + spotQuals[r][spot_id] = spotIntensities[r][spot_id] / norm return spotQuals def barcodeBuildFunc(allNeighbors: list, - channelDict: dict, currentRound: int, roundOmitNum: int, roundNum: int) -> list: @@ -306,8 +245,6 @@ def barcodeBuildFunc(allNeighbors: list, ---------- allNeighbors : list List of neighbor from which to build barcodes from - channelDict : dict - Dictionary mapping spot IDs to their channels labels currentRound : int The round that the spots being used for reference points are found in roundOmitNum : int @@ -345,7 +282,6 @@ def barcodeBuildFunc(allNeighbors: list, def buildBarcodes(roundData: pd.DataFrame, neighborDict: dict, roundOmitNum: int, - channelDict: dict, strictness: int, currentRound: int, numJobs: int) -> pd.DataFrame: @@ -407,8 +343,8 @@ def buildBarcodes(roundData: pd.DataFrame, # Run in parallel with ProcessPoolExecutor() as pool: - part = partial(barcodeBuildFunc, channelDict=channelDict, currentRound=currentRound, - roundOmitNum=roundOmitNum, roundNum=roundNum) + part = partial(barcodeBuildFunc, currentRound=currentRound, roundOmitNum=roundOmitNum, + roundNum=roundNum) poolMap = pool.map(part, [chunkedNeighbors[i] for i in range(len(chunkedNeighbors))]) results = [x for x in poolMap] @@ -443,7 +379,7 @@ def generateRoundPermutations(size: int, roundOmitNum: int) -> list: return sorted(set(list(permutations([*([False] * roundOmitNum), *([True] * (size - roundOmitNum))])))) -def decodeFunc(data: pd.DataFrame, permutationCodes: dict) -> tuple: +def decodeFunc(data: pd.DataFrame) -> tuple: ''' Subfunction for decoder that allows it to run in parallel chunks @@ -472,7 +408,7 @@ def decodeFunc(data: pd.DataFrame, permutationCodes: dict) -> tuple: # Try to assign target by using barcode as key in permutationsCodes dictionary for # current set of rounds. If there is no barcode match, it will error and go to the # except and if it succeeds it will add the data to the other lists for this barcode - targets.append(permutationCodes[barcode]) + targets.append(globPermutationCodes[barcode]) # type: ignore decodedSpotCodes.append(allSpotCodes[i][j]) except Exception: pass @@ -480,6 +416,10 @@ def decodeFunc(data: pd.DataFrame, permutationCodes: dict) -> tuple: allDecodedSpotCodes.append(decodedSpotCodes) return (allTargets, allDecodedSpotCodes) +def setGlobalDecoder(permutationCodes): + global globPermutationCodes + globPermutationCodes = permutationCodes + def decoder(roundData: pd.DataFrame, codebook: Codebook, channelDict: dict, @@ -552,8 +492,9 @@ def decoder(roundData: pd.DataFrame, chunkedData.append(deepcopy(roundData[ranges[i]:ranges[i + 1]])) # Run in parallel - with ProcessPoolExecutor() as pool: - part = partial(decodeFunc, permutationCodes=permCodeDict) + with ProcessPoolExecutor(max_workers=numJobs, initializer=setGlobalDecoder, + initargs=(permCodeDict,)) as pool: + part = partial(decodeFunc) poolMap = pool.map(part, [chunkedData[i] for i in range(len(chunkedData))]) results = [x for x in poolMap] @@ -574,24 +515,15 @@ def decoder(roundData: pd.DataFrame, return roundData def distanceFunc(spotsAndTargets: list, - spotCoords: dict, - spotQualDict: dict, currentRoundOmitNum: int) -> tuple: ''' Subfunction for distanceFilter to allow it to run in parallel Parameters ---------- - subSpotCodes : list - Chunk of full list of spot codes for the current round to calculate the spatial - variance for - subSpotCodes : list - Chunk of full list of targets (0s if strictness is positive) associated with the - current set of spots whose spatial variance is being calculated - spotCoords : dict - Spot ID to spatial coordinate dictionary - spotQualDict : dict - Spot ID to normalized intensity value dictionary + spotsAndTargets : list + First element contains current spot code set while 2nd element contains target names (if + decoded already) currentRoundOmitNum : int Number of rounds that can be dropped from each barcode Returns @@ -609,12 +541,13 @@ def distanceFunc(spotsAndTargets: list, bestDistances = [] bestTargets = [] for i, codes in enumerate(subSpotCodes): - quals = [sum([spotQualDict[r][spot] for r, spot in enumerate(code) if spot != 0]) - for code in codes] - newQuals = np.asarray([-np.log(1 / (1 + (len(spotCoords) - currentRoundOmitNum - qual))) + quals = [sum([globSpotQualDict[r][spot] for r, spot in enumerate(code) # type: ignore + if spot != 0]) for code in codes] + newQuals = np.asarray([-np.log(1 / (1 + (len(globSpotCoords) # type: ignore + - currentRoundOmitNum - qual))) for qual in quals]) - subCoords = [[spotCoords[r][spot] for r, spot in enumerate(code) if spot != 0] - for code in codes] + subCoords = [[globSpotCoords[r][spot] for r, spot in enumerate(code) # type: ignore + if spot != 0] for code in codes] spaVars = [sum(np.var(np.asarray(coords), axis=0)) for coords in subCoords] newSpaVars = np.asarray([-np.log(1 / (1 + spaVar)) for spaVar in spaVars]) combined = newQuals + (newSpaVars * constant) @@ -630,6 +563,12 @@ def distanceFunc(spotsAndTargets: list, return (bestSpotCodes, bestDistances, bestTargets) +def setGlobalDistance(spotCoords, spotQualDict): + global globSpotCoords + global globSpotQualDict + globSpotCoords = spotCoords + globSpotQualDict = spotQualDict + def distanceFilter(roundData: pd.DataFrame, spotCoords: dict, spotQualDict: dict, @@ -696,9 +635,9 @@ def distanceFilter(roundData: pd.DataFrame, chunkedTargets = [allTargets[ranges[i]:ranges[i + 1]] for i in range(len(ranges[:-1]))] # Run in parallel - with ProcessPoolExecutor() as pool: - part = partial(distanceFunc, spotCoords=spotCoords, spotQualDict=spotQualDict, - currentRoundOmitNum=currentRoundOmitNum) + with ProcessPoolExecutor(max_workers=numJobs, initializer=setGlobalDistance, + initargs=(spotCoords, spotQualDict)) as pool: + part = partial(distanceFunc, currentRoundOmitNum=currentRoundOmitNum) poolMap = pool.map(part, [spotsAndTargets for spotsAndTargets in zip(chunkedSpotCodes, chunkedTargets)]) results = [x for x in poolMap] diff --git a/starfish/core/spots/FindSpots/blob.py b/starfish/core/spots/FindSpots/blob.py index 103043ce7..4146e0daf 100644 --- a/starfish/core/spots/FindSpots/blob.py +++ b/starfish/core/spots/FindSpots/blob.py @@ -1,3 +1,4 @@ +from collections import defaultdict from functools import partial from typing import Optional, Tuple, Union @@ -24,7 +25,6 @@ 'blob_log': blob_log } - class BlobDetector(FindSpotsAlgorithm): """ Multi-dimensional gaussian spot detector @@ -121,6 +121,10 @@ def image_to_spots( if self.detector_method is not blob_doh: spot_finding_args["exclude_border"] = self.exclude_border + # Causes error otherwise + if self.detector_method == blob_dog: + del spot_finding_args['num_sigma'] + fitted_blobs_array: np.ndarray = self.detector_method( data_image, **spot_finding_args @@ -132,12 +136,19 @@ def image_to_spots( return PerImageSliceSpotResults(spot_attrs=empty_spot_attrs, extras=None) # measure intensities - z_inds = fitted_blobs_array[:, 0].astype(int) - y_inds = fitted_blobs_array[:, 1].astype(int) - x_inds = fitted_blobs_array[:, 2].astype(int) - radius = np.round(fitted_blobs_array[:, 3] * np.sqrt(3)) data_image = np.asarray(data_image) - intensities = data_image[tuple([z_inds, y_inds, x_inds])] + if self.is_volume: + z_inds = fitted_blobs_array[:, 0].astype(int) + y_inds = fitted_blobs_array[:, 1].astype(int) + x_inds = fitted_blobs_array[:, 2].astype(int) + radius = np.round(fitted_blobs_array[:, 3] * np.sqrt(3)) + intensities = data_image[tuple([z_inds, y_inds, x_inds])] + else: + z_inds = np.asarray([0 for x in range(len(fitted_blobs_array))]) + y_inds = fitted_blobs_array[:, 0].astype(int) + x_inds = fitted_blobs_array[:, 1].astype(int) + radius = np.round(fitted_blobs_array[:, 2] * np.sqrt(3)) + intensities = data_image[tuple([y_inds, x_inds])] # construct dataframe spot_data = pd.DataFrame( @@ -195,6 +206,28 @@ def run( group_by=determine_axes_to_group_by(self.is_volume), n_processes=n_processes ) + + # If not a volume, merge spots from the same round/channel but different z slices + if not self.is_volume: + merged_z_tables = defaultdict(pd.DataFrame) # type: ignore + for i in range(len(spot_attributes_list)): + spot_attributes_list[i][0].spot_attrs.data['z'] = \ + spot_attributes_list[i][1]['z'] + r = spot_attributes_list[i][1][Axes.ROUND] + ch = spot_attributes_list[i][1][Axes.CH] + merged_z_tables[(r, ch)] = merged_z_tables[(r, ch)].append( + spot_attributes_list[i][0].spot_attrs.data) + new = [] + r_chs = sorted([*merged_z_tables]) + selectors = list(image_stack._iter_axes({Axes.ROUND, Axes.CH})) + for i, (r, ch) in enumerate(r_chs): + merged_z_tables[(r, ch)]['spot_id'] = range(len(merged_z_tables[(r, ch)])) + spot_attrs = SpotAttributes(merged_z_tables[(r, ch)].reset_index(drop=True)) + new.append((PerImageSliceSpotResults(spot_attrs=spot_attrs, extras=None), + selectors[i])) + + spot_attributes_list = new + results = SpotFindingResults(imagestack_coords=image_stack.xarray.coords, log=image_stack.log, spot_attributes_list=spot_attributes_list) diff --git a/starfish/core/types/_spot_finding_results.py b/starfish/core/types/_spot_finding_results.py index b3dc71d65..47a328746 100644 --- a/starfish/core/types/_spot_finding_results.py +++ b/starfish/core/types/_spot_finding_results.py @@ -1,12 +1,13 @@ +import json +import os from dataclasses import dataclass -from typing import Any, Hashable, Mapping, MutableMapping, Optional, Sequence, Tuple +from typing import Any, Dict, Hashable, Mapping, MutableMapping, Optional, Sequence, Tuple import xarray as xr from starfish.core.types import Axes, Coordinates, SpotAttributes from starfish.core.util.logging import Log - AXES_ORDER = (Axes.ROUND, Axes.CH) @@ -36,7 +37,6 @@ def __init__( ): """ Construct a SpotFindingResults instance - Parameters ----------- imagestack_coords : xr.CoordinateArray @@ -64,7 +64,6 @@ def __init__( def __setitem__(self, indices: Mapping[Axes, int], value: PerImageSliceSpotResults): """ Add the round, ch indices and corresponding SpotAttributes to the results dict. - Parameters ---------- indices: Mapping[Axes, int] @@ -78,12 +77,10 @@ def __setitem__(self, indices: Mapping[Axes, int], value: PerImageSliceSpotResul def __getitem__(self, indices: Mapping[Axes, int]) -> PerImageSliceSpotResults: """ Returns the spots found in a given round and ch. - Parameters ---------- indices: Mapping[Axes, int] Mapping of Axes to int values - Returns -------- SpotAttributes @@ -109,6 +106,93 @@ def values(self): """ return self._results.values() + def save(self, output_dir_name: str) -> None: + """Save spot finding results to series of files. + Parameters + ---------- + output_dir_name: str + Location to save all files. + """ + json_data: Dict[str, Any] = {} + + pwd = os.getcwd() + os.chdir(os.path.dirname(output_dir_name)) + base_name = os.path.basename(output_dir_name) + + coords = {} + for key in self.physical_coord_ranges.keys(): + path = "{}coords_{}.nc".format(base_name, key) + coords[key] = path + self.physical_coord_ranges[key].to_netcdf(path) + json_data["physical_coord_ranges"] = coords + + path = "{}log.arr" + json_data["log"] = {} + json_data["log"]["path"] = path.format(base_name) + with open(path.format(base_name), "w") as f: + f.write(self.log.encode()) + + spot_attrs = {} + for key in self._results.keys(): + path = "{}spots_{}_{}.nc".format(base_name, key[0], key[1]) + spot_attrs["{}_{}".format(key[0], key[1])] = path + self._results[key].spot_attrs.save(path) + json_data["spot_attrs"] = spot_attrs + + save = json.dumps(json_data) + with open("{}SpotFindingResults.json".format(base_name), "w") as f: + f.write(save) + + os.chdir(pwd) + + @classmethod + def load(cls, json_file: str): + """Load serialized spot finding results. + Parameters: + ----------- + json_file: str + json file to read + Returns: + -------- + SpotFindingResults: + Object containing loaded results + """ + fl = open(json_file) + data = json.load(fl) + pwd = os.getcwd() + + os.chdir(os.path.dirname(json_file)) + + with open(data["log"]["path"]) as f: + txt = json.load(f)['log'] + txt = json.dumps(txt) + log = Log.decode(txt) + + rename_axes = { + 'x': Coordinates.X.value, + 'y': Coordinates.Y.value, + 'z': Coordinates.Z.value + } + coords = {} + for coord, path in data["physical_coord_ranges"].items(): + coords[rename_axes[coord]] = xr.load_dataarray(path) + + spot_attributes_list = [] + for key, path in data["spot_attrs"].items(): + zero = int(key.split("_")[0]) + one = int(key.split("_")[1]) + index = {AXES_ORDER[0]: zero, AXES_ORDER[1]: one} + spots = SpotAttributes.load(path) + spot_attributes_list.append((PerImageSliceSpotResults(spots, extras=None), index)) + + os.chdir(pwd) + + return SpotFindingResults( + imagestack_coords=coords, + log=log, + spot_attributes_list=spot_attributes_list + ) + @property def round_labels(self): """ @@ -146,11 +230,9 @@ def log(self) -> Log: """ Returns a list of pipeline components that have been applied to this get these SpotResults as well as their corresponding runtime parameters. - For more information about provenance logging see `Provenance Logging `_ - Returns ------- Log diff --git a/starfish/core/types/test/test_saving_spots.py b/starfish/core/types/test/test_saving_spots.py new file mode 100644 index 000000000..a6c79dc01 --- /dev/null +++ b/starfish/core/types/test/test_saving_spots.py @@ -0,0 +1,69 @@ +import os +import tempfile + +import numpy as np +import pandas as pd +import xarray as xr + +from starfish.core.types import PerImageSliceSpotResults, SpotAttributes, SpotFindingResults +from starfish.core.util.logging import Log +from starfish.types import Axes, Coordinates, Features + +def dummy_spots() -> SpotFindingResults: + rounds = 4 + channels = 3 + spot_count = 100 + img_dim = {'x': 2048, 'y': 2048, 'z': 29} + + coords = {} + renameAxes = { + 'x': Coordinates.X.value, + 'y': Coordinates.Y.value, + 'z': Coordinates.Z.value + } + for dim in img_dim.keys(): + coords[renameAxes[dim]] = xr.DataArray(np.arange(0, 1, img_dim[dim])) + + log = Log() + + spot_attributes_list = [] + for r in range(rounds): + for c in range(channels): + index = {Axes.ROUND: r, Axes.CH: c} + spots = SpotAttributes(pd.DataFrame( + np.random.randint(0, 100, size=(spot_count, 4)), + columns=[Axes.X.value, + Axes.Y.value, + Axes.ZPLANE.value, + Features.SPOT_RADIUS] + )) + spot_attributes_list.append( + (PerImageSliceSpotResults(spots, extras=None), index) + ) + + return SpotFindingResults( + imagestack_coords=coords, + log=log, + spot_attributes_list=spot_attributes_list + ) + +def test_saving_spots() -> None: + data = dummy_spots() + + # test serialization + tempdir = tempfile.mkdtemp() + print(tempdir) + data.save(tempdir + "/") + + # load back into memory + data2 = SpotFindingResults.load(os.path.join(tempdir, 'SpotFindingResults.json')) + + # ensure all items are equal + assert data.keys() == data2.keys() + assert data._log.encode() == data2._log.encode() + for ax in data.physical_coord_ranges.keys(): + np.testing.assert_equal(data.physical_coord_ranges[ax].to_numpy(), + data2.physical_coord_ranges[ax].to_numpy()) + for k in data._results.keys(): + np.testing.assert_array_equal(data._results[k].spot_attrs.data, + data2._results[k].spot_attrs.data)