From 34aee5bf4f19916946d1bae6624cc2ab734497c7 Mon Sep 17 00:00:00 2001 From: j1c Date: Sun, 5 Nov 2017 13:04:09 -0500 Subject: [PATCH 1/3] remove labeling of ground truth --- source/bstadt/Quality/Quality.py | 39 +- source/bstadt/Util/Util.py | 3 + .../j1c/quality/compute_overlaps_test.ipynb | 360 ++++++++++++++++++ 3 files changed, 391 insertions(+), 11 deletions(-) create mode 100644 source/j1c/quality/compute_overlaps_test.ipynb diff --git a/source/bstadt/Quality/Quality.py b/source/bstadt/Quality/Quality.py index e3b30e7..dab9cd5 100644 --- a/source/bstadt/Quality/Quality.py +++ b/source/bstadt/Quality/Quality.py @@ -1,17 +1,37 @@ import numpy as np from skimage.measure import label + +def get_uniques(ar): + """ + Returns an ordered numpy array of unique integers in an array. + This runs about four times faster than numpy.unique(). + + Parameters + ---------- + ar : array_like + Input array. This will be flattened. + + Returns + ------- + uniques : ndarray + The sorted unique values. + """ + bins = np.zeros(np.max(ar) + 1, dtype=int) + bins[ar.ravel()] = 1 + uniques = np.nonzero(bins)[0] + + return uniques + + def get_unique_overlap(foreground, background, i): ''' Calculates the number of unique background labels in the foreground at i Does not count background label of 0 ''' - #This runs about 4 times faster than np.unique() overlaps = np.multiply((foreground == i), background) - bins = np.zeros(np.max(overlaps) + 1, dtype=int) - bins[overlaps.ravel()] = 1 - uniques = np.nonzero(bins)[0] + uniques = get_uniques(overlaps) num_unique = len(uniques) @@ -25,22 +45,19 @@ def get_unique_overlap(foreground, background, i): def compute_overlap_array(predictions, gt): - predictionLabels = label(predictions) maxPredictionLabel = np.max(predictionLabels) - gtLabels = label(gt) - maxGtLabel = np.max(gtLabels) + gt_uniques = get_uniques(gt)[1:] #first, look at how many unique predictions #overlap with a single gt synapse - predictionPerGt = [get_unique_overlap(gtLabels, predictionLabels, i)\ - for i in range(1, maxGtLabel + 1)] - + predictionPerGt = [get_unique_overlap(gt, predictionLabels, i) + for i in gt_uniques] #next, look at how many unique synapses overlap #with a single synapse prediction - gtPerPrediction = [get_unique_overlap(predictionLabels, gtLabels, i)\ + gtPerPrediction = [get_unique_overlap(predictionLabels, gt, i) for i in range(1, maxPredictionLabel + 1)] return {'predictionPerGt': predictionPerGt, diff --git a/source/bstadt/Util/Util.py b/source/bstadt/Util/Util.py index 830cbbd..6c99116 100644 --- a/source/bstadt/Util/Util.py +++ b/source/bstadt/Util/Util.py @@ -1,3 +1,6 @@ +import numpy as np +from random import randrange as rand + def delta_epsilon(a, b, e): return abs(a-b) < e diff --git a/source/j1c/quality/compute_overlaps_test.ipynb b/source/j1c/quality/compute_overlaps_test.ipynb new file mode 100644 index 0000000..42a43a5 --- /dev/null +++ b/source/j1c/quality/compute_overlaps_test.ipynb @@ -0,0 +1,360 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "import sys\n", + "sys.path.append('../../bstadt/Quality/')\n", + "sys.path.append('../../bstadt/Util/')\n", + "\n", + "from Quality import compute_overlap_array as bstadt_overlaps\n", + "from Util import generateTestVolume\n", + "from skimage.measure import label" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "data = np.load('../data/collman15v2.npz')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['annotation',\n", + " 'EM25K',\n", + " 'GABA488',\n", + " 'GAD647',\n", + " 'gephyrin594',\n", + " 'GS594',\n", + " 'MBP488',\n", + " 'NR1594',\n", + " 'PSD95_488',\n", + " 'Synapsin647',\n", + " 'VGluT1_647',\n", + " 'DAPI1st']" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data.files" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "annotation = data['annotation']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Check results from bstadt compute_overlap_array to make sure it is creating more ground truth labels" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#Just look at the middle section with shape (20, 2000, 2000)\n", + "annotation = annotation[0:20, 2000:4000, 2000:4000]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "37\n", + "52\n" + ] + } + ], + "source": [ + "#This section has 37 annotations\n", + "print(len(np.unique(annotation)[1:]))\n", + "\n", + "#Labeling annotations results in 52 labels\n", + "print(len(np.unique(label(annotation))[1:]))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "#Generate a random \"prediction\" volume with shape (20, 2000, 2000) with 40 predictions\n", + "test_volume, _ = generateTestVolume(20, 2000, 2000, \n", + " 40,\n", + " 41,\n", + " 3,\n", + " 5,\n", + " 10,\n", + " 25,\n", + " 10,\n", + " 25)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "40" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#Confirm there are 40 \"predictions\"\n", + "len(np.unique(label(test_volume))[1:])" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "bstadt_results = bstadt_overlaps(test_volume, annotation)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "predictionPerGt should have 52 values in bstadt_results" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "predictionPerGt 52\n", + "gtPerPrediction 40\n" + ] + } + ], + "source": [ + "for key, value in bstadt_results.items():\n", + " print(key, len(value))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Remove labeling of ground truth. Should result in \"predictionPerGt\" to be 37 in this case." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def get_uniques(ar):\n", + " \"\"\"\n", + " Returns an ordered numpy array of unique integers in an array.\n", + " This runs about four times faster than numpy.unique().\n", + "\n", + " Parameters\n", + " ----------\n", + " ar : array_like\n", + "\n", + " Returns\n", + " -------\n", + " uniques :\n", + " \"\"\"\n", + " bins = np.zeros(np.max(ar) + 1, dtype=int)\n", + " bins[ar.ravel()] = 1\n", + " uniques = np.nonzero(bins)[0]\n", + "\n", + " return uniques\n", + "\n", + "def get_unique_overlap2(foreground, background, i):\n", + " '''\n", + " Calculates the number of unique background labels in the foreground at i\n", + " Does not count background label of 0\n", + " '''\n", + "\n", + " overlaps = np.multiply((foreground == i), background)\n", + " uniques = get_uniques(overlaps)\n", + "\n", + " num_unique = len(uniques)\n", + "\n", + " #0 is background label\n", + " #should not count as a detection if\n", + " #the prediction overlaps with the background\n", + " if 0 in uniques:\n", + " num_unique -= 1\n", + "\n", + " return num_unique\n", + "\n", + "\n", + "def compute_overlap_array2(predictions, gt):\n", + " predictionLabels = label(predictions)\n", + " maxPredictionLabel = np.max(predictionLabels)\n", + "\n", + " #gtLabels = label(gt)\n", + " #maxGtLabel = np.max(gtLabels)\n", + " gt_uniques = get_uniques(gt)[1:]\n", + "\n", + "\n", + " #first, look at how many unique predictions\n", + " #overlap with a single gt synapse\n", + " predictionPerGt = [get_unique_overlap2(gt, predictionLabels, i)\\\n", + " for i in gt_uniques]\n", + "\n", + "\n", + " #next, look at how many unique synapses overlap\n", + " #with a single synapse prediction\n", + " gtPerPrediction = [get_unique_overlap2(predictionLabels, gt, i)\\\n", + " for i in range(1, maxPredictionLabel + 1)]\n", + "\n", + " return {'predictionPerGt': predictionPerGt,\n", + " 'gtPerPrediction': gtPerPrediction}\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "j1c_results = compute_overlap_array2(test_volume, annotation)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This should result in predictionPerGt with 37 values" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "predictionPerGt 37\n", + "gtPerPrediction 40\n" + ] + } + ], + "source": [ + "for key, value in j1c_results.items():\n", + " print(key, len(value))" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.array_equiv(get_uniques(annotation), np.unique(annotation))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 56c3fb8d48af7d5faa6bc40a041fb15a9926be5c Mon Sep 17 00:00:00 2001 From: j1c Date: Mon, 6 Nov 2017 00:37:38 -0500 Subject: [PATCH 2/3] Compute overlaps optimization --- source/bstadt/Quality/Quality.py | 37 +- .../compute_overlaps_optimization.ipynb | 345 ++++++++++++++++++ 2 files changed, 376 insertions(+), 6 deletions(-) create mode 100644 source/j1c/quality/compute_overlaps_optimization.ipynb diff --git a/source/bstadt/Quality/Quality.py b/source/bstadt/Quality/Quality.py index dab9cd5..66024d9 100644 --- a/source/bstadt/Quality/Quality.py +++ b/source/bstadt/Quality/Quality.py @@ -1,6 +1,21 @@ import numpy as np from skimage.measure import label +def bounding_box(img): + """ + Returns the z, y, x vectors that create a bounding box + of a mask. + """ + z = np.any(img, axis=(1, 2)) + y = np.any(img, axis=(0, 2)) + x = np.any(img, axis=(0, 1)) + + zmin, zmax = np.where(z)[0][[0, -1]] + ymin, ymax = np.where(y)[0][[0, -1]] + xmin, xmax = np.where(x)[0][[0, -1]] + + return (zmin, zmax + 1), (ymin, ymax + 1), (xmin, xmax + 1) + def get_uniques(ar): """ @@ -29,6 +44,10 @@ def get_unique_overlap(foreground, background, i): Calculates the number of unique background labels in the foreground at i Does not count background label of 0 ''' + z, y, x = bounding_box(foreground == i) + + foreground = foreground[z[0]:z[1], y[0]:y[1], x[0]:x[1]] + background = background[z[0]:z[1], y[0]:y[1], x[0]:x[1]] overlaps = np.multiply((foreground == i), background) uniques = get_uniques(overlaps) @@ -44,21 +63,27 @@ def get_unique_overlap(foreground, background, i): return num_unique -def compute_overlap_array(predictions, gt): - predictionLabels = label(predictions) - maxPredictionLabel = np.max(predictionLabels) +def compute_overlap_array(predictions, gt, compare_annotations=False): + """ + When comparing two annotation volumes, set compare_annotations to True. + """ + if not compare_annotations: + predictions = label(predictions) + prediction_uniques = get_uniques(predictions)[1:] + elif compare_annotations: + prediction_uniques = get_uniques(predictions) gt_uniques = get_uniques(gt)[1:] #first, look at how many unique predictions #overlap with a single gt synapse - predictionPerGt = [get_unique_overlap(gt, predictionLabels, i) + predictionPerGt = [get_unique_overlap(gt, predictions, i) for i in gt_uniques] #next, look at how many unique synapses overlap #with a single synapse prediction - gtPerPrediction = [get_unique_overlap(predictionLabels, gt, i) - for i in range(1, maxPredictionLabel + 1)] + gtPerPrediction = [get_unique_overlap(predictions, gt, i) + for i in prediction_uniques] return {'predictionPerGt': predictionPerGt, 'gtPerPrediction': gtPerPrediction} diff --git a/source/j1c/quality/compute_overlaps_optimization.ipynb b/source/j1c/quality/compute_overlaps_optimization.ipynb new file mode 100644 index 0000000..cfd7a5e --- /dev/null +++ b/source/j1c/quality/compute_overlaps_optimization.ipynb @@ -0,0 +1,345 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Compute_overlap_array is too slow when comparing two annotation volumes\n", + "\n", + "In fact, the time is almost quadratic in relation to the array size and linearly in relation to number of annotations. We can get close to linear time given two annotation volumes by:\n", + " 1. Create a tight bounding box around a prediction or a ground truth\n", + " 2. Calculate the overlaps only on the bounding box volume." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "from skimage.measure import label\n", + "\n", + "import sys\n", + "sys.path.append('../../bstadt/Quality/')\n", + "\n", + "from Quality import compute_overlap_array" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "from skimage.measure import label\n", + "\n", + "def bounding_box(img):\n", + " \"\"\"\n", + " Returns the z, y, x vectors that create a bounding box\n", + " of a mask.\n", + " \"\"\"\n", + " z = np.any(img, axis=(1, 2))\n", + " y = np.any(img, axis=(0, 2))\n", + " x = np.any(img, axis=(0, 1))\n", + "\n", + " zmin, zmax = np.where(z)[0][[0, -1]]\n", + " ymin, ymax = np.where(y)[0][[0, -1]]\n", + " xmin, xmax = np.where(x)[0][[0, -1]]\n", + "\n", + " return (zmin, zmax + 1), (ymin, ymax + 1), (xmin, xmax + 1)\n", + "\n", + "\n", + "def get_uniques(ar):\n", + " \"\"\"\n", + " Returns an ordered numpy array of unique integers in an array.\n", + " This runs about four times faster than numpy.unique().\n", + "\n", + " Parameters\n", + " ----------\n", + " ar : array_like\n", + " Input array. This will be flattened.\n", + "\n", + " Returns\n", + " -------\n", + " uniques : ndarray\n", + " The sorted unique values.\n", + " \"\"\"\n", + " bins = np.zeros(np.max(ar) + 1, dtype=int)\n", + " bins[ar.ravel()] = 1\n", + " uniques = np.nonzero(bins)[0]\n", + "\n", + " return uniques\n", + "\n", + "\n", + "def get_unique_overlap2(foreground, background, i):\n", + " '''\n", + " Calculates the number of unique background labels in the foreground at i\n", + " Does not count background label of 0\n", + " '''\n", + " z, y, x = bounding_box(foreground == i)\n", + " \n", + " foreground = foreground[z[0]:z[1], y[0]:y[1], x[0]:x[1]]\n", + " background = background[z[0]:z[1], y[0]:y[1], x[0]:x[1]]\n", + " \n", + " overlaps = np.multiply((foreground == i), background)\n", + " uniques = get_uniques(overlaps)\n", + "\n", + " num_unique = len(uniques)\n", + "\n", + " #0 is background label\n", + " #should not count as a detection if\n", + " #the prediction overlaps with the background\n", + " if 0 in uniques:\n", + " num_unique -= 1\n", + "\n", + " return num_unique\n", + "\n", + "\n", + "def compute_overlap_array2(predictions, gt, compare_annotations=False):\n", + " if not compare_annotations:\n", + " predictions = label(predictions)\n", + " prediction_uniques = get_uniques(predictions)[1:]\n", + " elif compare_annotations:\n", + " prediction_uniques = get_uniques(predictions)\n", + "\n", + " gt_uniques = get_uniques(gt)[1:]\n", + "\n", + " #first, look at how many unique predictions\n", + " #overlap with a single gt synapse\n", + " predictionPerGt = [get_unique_overlap2(gt, predictions, i)\n", + " for i in gt_uniques]\n", + "\n", + " #next, look at how many unique synapses overlap\n", + " #with a single synapse prediction\n", + " gtPerPrediction = [get_unique_overlap2(predictions, gt, i)\n", + " for i in prediction_uniques]\n", + "\n", + " return {'predictionPerGt': predictionPerGt,\n", + " 'gtPerPrediction': gtPerPrediction}\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "file = np.load('../data/collman15v2.npz')\n", + "collman_annotation = file['annotation']\n", + "\n", + "file = np.load('../../dmannan/Annotations/annotation_drishti.npz')\n", + "drishti_annotation = file['annotation_drishti']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First make sure the outputs are the same" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "compute_overlap_array(drishti_annotation[0:10, 1000:2000, 1000:2000], \\\n", + " collman_annotation[0:10, 1000:2000, 1000:2000])\\\n", + "== compute_overlap_array2(drishti_annotation[0:10, 1000:2000, 1000:2000], \\\n", + " collman_annotation[0:10, 1000:2000, 1000:2000])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For array size (10, 1000, 1000), it takes:\n", + " 1. without bounding box: 1.17s\n", + " 2. with bounding box: 409ms" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.17 s ± 34.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit -n1 compute_overlap_array(drishti_annotation[0:10, 1000:2000, 1000:2000], \\\n", + " collman_annotation[0:10, 1000:2000, 1000:2000])" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "409 ms ± 14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit -n1 compute_overlap_array2(drishti_annotation[0:10, 1000:2000, 1000:2000], \\\n", + " collman_annotation[0:10, 1000:2000, 1000:2000])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For array size (10, 2000, 2000), which is 4 times larger than (10, 1000, 1000), it takes:\n", + " 1. without bounding box: 15.2s\n", + " 2. with bounding box: 3.15s" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15.2 s ± 663 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit -n1 compute_overlap_array(drishti_annotation[0:10, 1000:3000, 1000:3000], \\\n", + " collman_annotation[0:10, 1000:3000, 1000:3000])" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.15 s ± 106 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit -n1 compute_overlap_array2(drishti_annotation[0:10, 1000:3000, 1000:3000], \\\n", + " collman_annotation[0:10, 1000:3000, 1000:3000])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For array size (20, 2000, 2000), which is 8 times larger than (10, 1000, 1000), it takes:\n", + " 1. without bounding box: 63s\n", + " 2. with bounding box: 11.6s" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1min 3s ± 6.35 s per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit -n1 compute_overlap_array(drishti_annotation[0:20, 1000:3000, 1000:3000], \\\n", + " collman_annotation[0:20, 1000:3000, 1000:3000])" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "11.6 s ± 956 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit -n1 compute_overlap_array2(drishti_annotation[0:20, 1000:3000, 1000:3000], \\\n", + " collman_annotation[0:20, 1000:3000, 1000:3000])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Not really going to compare the entire volume since it takes about two hours to run." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [default]", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 2f89c70c015d7e3f2ac4c7985d611078d7e43fa5 Mon Sep 17 00:00:00 2001 From: j1c Date: Mon, 6 Nov 2017 00:40:39 -0500 Subject: [PATCH 3/3] fixed typo --- source/bstadt/Quality/Quality.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/bstadt/Quality/Quality.py b/source/bstadt/Quality/Quality.py index 66024d9..8d6348e 100644 --- a/source/bstadt/Quality/Quality.py +++ b/source/bstadt/Quality/Quality.py @@ -71,7 +71,7 @@ def compute_overlap_array(predictions, gt, compare_annotations=False): predictions = label(predictions) prediction_uniques = get_uniques(predictions)[1:] elif compare_annotations: - prediction_uniques = get_uniques(predictions) + prediction_uniques = get_uniques(predictions)[1:] gt_uniques = get_uniques(gt)[1:]