Skip to content

Commit

Permalink
Merge pull request #231 from yfukai/metric_utils_doc
Browse files Browse the repository at this point in the history
Updating metric utils doc, added __version__ and bump patch
  • Loading branch information
yfukai authored Nov 6, 2022
2 parents 3b85c44 + 784ef53 commit 5062bfd
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 37 deletions.
8 changes: 4 additions & 4 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,24 @@ You need Python 3.8+ and the following tools:
- Poetry_
- Nox_
- nox-poetry_
- poetry-bumpversion_

Install the package with development requirements:

.. code:: console
$ poetry install
You can now run an interactive Python session,
or the command-line interface:
You can now run an interactive shell session:

.. code:: console
$ poetry run python
$ poetry run laptrack
$ poetry shell
.. _Poetry: https://python-poetry.org/
.. _Nox: https://nox.thea.codes/
.. _nox-poetry: https://nox-poetry.readthedocs.io/
.. _poetry-bumpversion: https://github.com/monim67/poetry-bumpversion


How to test the project
Expand Down
15 changes: 12 additions & 3 deletions docs/examples/api_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
" %pip install -q --upgrade laptrack matplotlib pandas"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Important note** please restart the runtime when you're executing this notebook in Google Colaboratory."
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -64,8 +71,10 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Load the example point coordinates from a CSV file.\n",
"\n",
"`spots_df` has columns `[\"frame\", \"position_x\", \"position_y\"]` \n",
"(can be arbitrary, and the column names for trackign will be specified later)"
"(can be arbitrary, and the column names for tracking will be specified later)."
]
},
{
Expand Down Expand Up @@ -111,8 +120,8 @@
" track_dist_metric=\"sqeuclidean\", # The similarity metric for particles. See `scipy.spatial.distance.cdist` for allowed values.\n",
" splitting_dist_metric=\"sqeuclidean\",\n",
" merging_dist_metric=\"sqeuclidean\",\n",
" track_cost_cutoff=max_distance\n",
" ** 2, # the square of the cutoff distance for the \"sqeuclidean\" metric\n",
" # the square of the cutoff distance for the \"sqeuclidean\" metric\n",
" track_cost_cutoff=max_distance**2,\n",
" splitting_cost_cutoff=max_distance**2, # or False for non-splitting case\n",
" merging_cost_cutoff=max_distance**2, # or False for non-merging case\n",
")"
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/overlap_tracking.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is the core of this example: we can define arbitrary function as the metric to measure how points are close.\n",
"Here is the core of this example: we can define an arbitrary function as the metric to measure how points are close.\n",
"\n",
"In this example, `metric` function retrive the pre-computed overlap between the segmented regions, and use\n",
"$$\n",
Expand Down
7 changes: 7 additions & 0 deletions docs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,10 @@ score calculation utilities

.. automodule:: laptrack.scores
:members:

metric utilities
-------------------------------

.. automodule:: laptrack.metric_utils
:members:
:special-members: __init__
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "laptrack"
version = "0.9.0"
version = "0.9.1"
description = "LapTrack"
authors = ["Yohsuke Fukai <[email protected]>"]
license = "BSD-3-Clause"
Expand Down Expand Up @@ -83,3 +83,5 @@ show_error_context = true
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry_bumpversion.file."src/laptrack/__init__.py"]
2 changes: 2 additions & 0 deletions src/laptrack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@
"scores",
"metric_utils",
]

__version__ = "0.9.1"
12 changes: 9 additions & 3 deletions src/laptrack/metric_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Utilities for metric calculation."""
from typing import List
from typing import Tuple
from typing import Union

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -32,14 +34,18 @@ def _union_bbox(self, r1, r2):
bbox.append((y0, y1))
return bbox

def __init__(self, label_images: IntArray):
def __init__(self, label_images: Union[IntArray, List[IntArray]]):
"""Summarise the segmentation properties and initialize the object.
Parameters
----------
label_images : IntArray
The labeled images. The first dimension is interpreted as the time dimension.
label_images : Union[IntArray,List[IntArray]]
The labeled images. The first dimension is interpreted as the frame dimension.
"""
if not isinstance(label_images, np.ndarray):
label_images = np.array(label_images)
if label_images.ndim < 3:
raise ValueError("label_images dimension must be >=3.")
self.label_images = label_images
self.ndim = label_images.ndim - 1
dfs = []
Expand Down
60 changes: 35 additions & 25 deletions tests/test_metric_utils.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,44 @@
from itertools import product
from typing import List
from typing import Union

import numpy as np
import pytest

from laptrack._typing_utils import IntArray
from laptrack.metric_utils import LabelOverlap


def test_label_overlap() -> None:
labels = np.array(
[
[[[0, 1, 1, 1, 0], [0, 1, 2, 2, 2]], [[0, 1, 2, 2, 2], [3, 3, 3, 1, 0]]],
[[[0, 1, 1, 1, 2], [0, 4, 1, 2, 2]], [[0, 4, 4, 4, 4], [0, 4, 4, 4, 4]]],
[[[0, 1, 1, 1, 0], [5, 5, 5, 5, 5]], [[0, 1, 1, 1, 0], [0, 1, 1, 1, 0]]],
]
)
lo = LabelOverlap(labels)
frame_labels = [np.unique(label) for label in labels]
frame_labels = [x[x > 0] for x in frame_labels]
for f1, f2 in [(0, 0), (0, 1), (1, 2)]:
for l1, l2 in product(frame_labels[f1], frame_labels[f2]):
b1 = labels[f1] == l1
b2 = labels[f2] == l2
labels = [
[[[0, 1, 1, 1, 0], [0, 1, 2, 2, 2]], [[0, 1, 2, 2, 2], [3, 3, 3, 1, 0]]],
[[[0, 1, 1, 1, 2], [0, 4, 1, 2, 2]], [[0, 4, 4, 4, 4], [0, 4, 4, 4, 4]]],
[[[0, 1, 1, 1, 0], [5, 5, 5, 5, 5]], [[0, 1, 1, 1, 0], [0, 1, 1, 1, 0]]],
]
labelss: List[Union[IntArray, List[IntArray]]] = [
np.array(labels),
[np.array(label).astype(np.int64) for label in labels],
]

intersect = np.sum(b1 & b2)
union = np.sum(b1 | b2)
r1 = np.sum(b1)
r2 = np.sum(b2)
res = lo.calc_overlap(f1, l1, f2, l2)
assert (
intersect,
(intersect / union),
(intersect / r1),
(intersect / r2),
) == res
for _labels in labelss:
lo = LabelOverlap(_labels)
frame_labels = [np.unique(label) for label in _labels]
frame_labels = [x[x > 0] for x in frame_labels]
for f1, f2 in [(0, 0), (0, 1), (1, 2)]:
for l1, l2 in product(frame_labels[f1], frame_labels[f2]):
b1 = _labels[f1] == l1
b2 = _labels[f2] == l2

intersect = np.sum(b1 & b2)
union = np.sum(b1 | b2)
r1 = np.sum(b1)
r2 = np.sum(b2)
res = lo.calc_overlap(f1, l1, f2, l2)
assert (
intersect,
(intersect / union),
(intersect / r1),
(intersect / r2),
) == res
with pytest.raises(ValueError):
LabelOverlap(np.array([[1, 2], [0, 1]]))

0 comments on commit 5062bfd

Please sign in to comment.