├── src
└── umetrix
│ ├── __init__.py
│ ├── render.py
│ ├── notebooks.py
│ └── core.py
├── .gitignore
├── tests
├── data
│ └── unet.tif
├── test_metrics.py
└── conftest.py
├── .github
└── workflows
│ ├── test.yml
│ └── linting.yml
├── pyproject.toml
├── .pre-commit-config.yaml
├── LICENSE.md
├── README.md
└── notebooks
└── unet_segmentation_metrics.ipynb
/src/umetrix/__init__.py:
--------------------------------------------------------------------------------
1 | from .core import calculate, batch # NOQA: F401
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.ipynb_checkpoints
2 | *.egg-info/
3 | .DS_Store
4 | __pycache__
5 | notebooks/
6 | _version.py
7 |
--------------------------------------------------------------------------------
/tests/data/unet.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lowe-lab-ucl/unet_segmentation_metrics/HEAD/tests/data/unet.tif
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | paths-ignore:
9 | - "**.md"
10 | - "**.rst"
11 |
12 | jobs:
13 | tests:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - name: Checkout source
17 | uses: actions/checkout@v3
18 |
19 | - name: Set up python
20 | uses: actions/setup-python@v4
21 | with:
22 | python-version: "3.10"
23 | cache: "pip"
24 | cache-dependency-path: "pyproject.toml"
25 |
26 | - name: Install dependencies
27 | run: |
28 | python -m pip install --upgrade pip
29 | python -m pip install pytest
30 |
31 | - name: Install umetrics
32 | run: |
33 | pip install -e .
34 | - name: Run tests
35 | run: |
36 | pytest
37 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools", "setuptools-scm"]
3 | build-backend = "setuptools.build_meta"
4 |
5 | [project]
6 | name = "umetrix"
7 | authors = [
8 | {name = "Alan R. Lowe", email = "a.lowe@ucl.ac.uk"}
9 | ]
10 | description = "UNet Segmentation Metrics"
11 | readme = "README.md"
12 | requires-python = ">=3.8"
13 | keywords = ["image analysis"]
14 | license = {text = "BSD-3-Clause"}
15 | classifiers = [
16 | "Programming Language :: Python :: 3"
17 | ]
18 | dependencies = [
19 | "matplotlib",
20 | "numpy",
21 | "pandas",
22 | "scikit-learn",
23 | "scikit-image>=0.20.0" # to include the spacing argument in regionprops
24 | ]
25 | dynamic = ["version"]
26 |
27 | [tool.setuptools.packages.find]
28 | where = ["src"]
29 | include = ["umetrix*"]
30 |
31 | [tool.setuptools_scm]
32 | local_scheme = "no-local-version"
33 | write_to = "src/umetrix/_version.py"
34 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/charliermarsh/ruff-pre-commit
3 | rev: v0.0.262
4 | hooks:
5 | - id: ruff
6 | - repo: https://github.com/pre-commit/pre-commit-hooks
7 | rev: v4.4.0
8 | hooks:
9 | - id: check-case-conflict
10 | - id: check-docstring-first
11 | - id: check-executables-have-shebangs
12 | - id: check-merge-conflict
13 | - id: check-toml
14 | - id: end-of-file-fixer
15 | - id: mixed-line-ending
16 | args: [--fix=lf]
17 | - id: trailing-whitespace
18 | args: [--markdown-linebreak-ext=md]
19 | - repo: https://github.com/psf/black
20 | rev: 23.3.0
21 | hooks:
22 | - id: black
23 | - repo: https://github.com/pappasam/toml-sort
24 | rev: v0.23.0
25 | hooks:
26 | - id: toml-sort-fix
27 |
--------------------------------------------------------------------------------
/.github/workflows/linting.yml:
--------------------------------------------------------------------------------
1 | name: Linting
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 |
9 | jobs:
10 | linting:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout source
14 | uses: actions/checkout@v3
15 |
16 | - name: Cache pre-commit
17 | uses: actions/cache@v3
18 | with:
19 | path: ~/.cache/pre-commit
20 | key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
21 |
22 | - name: Set up python
23 | uses: actions/setup-python@v4
24 | with:
25 | python-version: "3.x"
26 | cache: "pip"
27 | cache-dependency-path: "pyproject.toml"
28 |
29 | - name: Install dependencies
30 | run: |-
31 | python -m pip install pre-commit
32 | pre-commit install
33 |
34 | - name: Run pre-commit
35 | run: pre-commit run --all-files --color always
36 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Alan R. Lowe (quantumjot)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 | of the Software, and to permit persons to whom the Software is furnished to do
10 | so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://pypi.org/project/umetrix)
2 | [](https://github.com/psf/black)
3 | []([https://github.com/quantumjot/vne](https://github.com/lowe-lab-ucl/unet_segmentation_metrics)/actions/workflows/test.yml)
4 | [](https://github.com/pre-commit/pre-commit)
5 |
6 | # UNet segmentation metrics
7 |
8 | *WORK IN PROGRESS*
9 |
10 | Simple Python 3 tools to assess the performance of UNet segmentation networks
11 | (or any other segmentation method) by comparing the prediction to a ground truth
12 | image.
13 |
14 | Use it to calculate:
15 | + Jaccard metric for object detection
16 | + Intersection over Union (IoU) for object segmentation accuracy
17 | + Localization (positional) error for estimating MOTP during tracking
18 | + Pixel identity
19 |
20 | TODO:
21 | + [x] Add strict matching with IoU threshold
22 | + [ ] Add confusion matrix for multi-label/classification type tasks
23 |
24 |
25 | ### Single image usage
26 |
27 | ```python
28 | import umetrix
29 | from skimage.io import imread
30 |
31 | y_true = imread('true.tif')
32 | y_pred = imread('pred.tif')
33 |
34 |
35 | # can now make the calculation strict, by only considering objects that have
36 | # an IoU above a theshold as being true positives
37 | result = umetrix.calculate(
38 | y_true,
39 | y_pred,
40 | strict=True,
41 | iou_threshold=0.5
42 | )
43 |
44 | print(result.results)
45 | ```
46 |
47 | returns:
48 |
49 | ```
50 | ============================
51 | Segmentation Metrics (n=1)
52 | ============================
53 | Strict: True (IoU > 0.5)
54 | n_true_labels: 354
55 | n_pred_labels: 362
56 | n_true_positives: 345
57 | n_false_positives: 10
58 | n_false_negatives: 0
59 | IoU: 0.999
60 | Jaccard: 0.972
61 | pixel_identity: 0.998
62 | localization_error: 0.010
63 | ```
64 |
65 |
66 | ### Batch processing
67 |
68 | ```python
69 | import umetrix
70 |
71 | # provide a list of file pairs ('true', 'prediction')
72 | files = [
73 | ('true0.tif', 'pred0.tif'),
74 | ('true1.tif', 'pred1.tif'),
75 | ('true2.tif', 'pred2.tif')
76 | ]
77 |
78 | batch_result = umetrix.batch(files)
79 | ```
80 |
81 | Returns aggregate statistics over the batch. Jaccard index is calculated over
82 | all found objects, while other metrics are the average IoU etc.
83 |
84 |
85 | ### Installation
86 |
87 | 1. First clone the repo:
88 | ```sh
89 | $ git clone https://github.com/quantumjot/unet_segmentation_metrics.git
90 | ```
91 |
92 | 2. (Optional, but advised) Create a conda environment:
93 | ```sh
94 | $ conda create -n umetrix python=3.9
95 | $ conda activate umetrix
96 | ```
97 |
98 | 3. Install the package
99 | ```sh
100 | $ cd unet_segmentation_metrics
101 | $ pip install .
102 | ```
103 |
--------------------------------------------------------------------------------
/tests/test_metrics.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import numpy as np
3 |
4 | import umetrix
5 |
6 |
7 | STRICT_PARAMS = [(False, 0.0), (True, 0.1), (True, 0.2), (True, 0.5), (True, 0.7)]
8 |
9 |
10 | @pytest.mark.parametrize("strict,iou_threshold", STRICT_PARAMS)
11 | def test_calculate(image_pair, strict, iou_threshold):
12 | """Run the metrics on a pair of images."""
13 | y_true, y_pred, stats = image_pair
14 | IoU = stats["IoU"]
15 |
16 | result = umetrix.calculate(
17 | y_true, y_pred, strict=strict, iou_threshold=iou_threshold
18 | )
19 |
20 | # calculate the real number of true postives based on strict matching
21 | real_tp = int(IoU > result.iou_threshold) if strict else int(IoU > 0)
22 |
23 | assert result.n_true_labels == 1
24 | assert result.n_pred_labels == 1
25 | assert result.n_true_positives == real_tp
26 | assert result.n_false_positives == 1 - real_tp
27 |
28 |
29 | def test_calculate_no_true(image_pair):
30 | """Test a pair of images where there is no object in the GT."""
31 | y_true, y_pred, _ = image_pair
32 | y_true = np.zeros_like(y_pred)
33 |
34 | result = umetrix.calculate(y_true, y_pred)
35 | assert result.n_true_labels == 0
36 | assert result.n_pred_labels == 1
37 | assert result.n_true_positives == 0
38 | assert result.n_false_negatives == 0
39 | assert result.n_false_positives == 1
40 |
41 |
42 | def test_calculate_no_pred(image_pair):
43 | """Test a pair of images where there is no object in the prediction."""
44 | y_true, y_pred, _ = image_pair
45 | y_pred = np.zeros_like(y_true)
46 |
47 | result = umetrix.calculate(y_true, y_pred)
48 | assert result.n_true_labels == 1
49 | assert result.n_pred_labels == 0
50 | assert result.n_true_positives == 0
51 | assert result.n_false_negatives == 1
52 | assert result.n_false_positives == 0
53 |
54 |
55 | @pytest.mark.parametrize("strict,iou_threshold", STRICT_PARAMS)
56 | def test_calculate_grid(image_grid, strict, iou_threshold):
57 | """Test a multi-instance segmentation."""
58 | y_true, y_pred, stats = image_grid
59 | result = umetrix.calculate(
60 | y_true, y_pred, strict=strict, iou_threshold=iou_threshold
61 | )
62 |
63 | n_iou_over_threshold = sum([iou > iou_threshold for iou in stats["IoU"]])
64 | n_iou_under_threshold = stats["n_pairs"] - n_iou_over_threshold if strict else 0
65 | n_tp = n_iou_over_threshold
66 | n_fp = stats["n_false_positive"] + n_iou_under_threshold
67 | n_fn = stats["n_false_negative"] + n_iou_under_threshold
68 |
69 | assert result.n_true_labels == stats["n_true"]
70 | assert result.n_pred_labels == stats["n_pred"]
71 | assert result.n_true_positives == n_tp
72 | assert result.n_false_positives == n_fp
73 | assert result.n_false_negatives == n_fn
74 |
75 |
76 | @pytest.mark.parametrize("strict,iou_threshold", STRICT_PARAMS)
77 | def test_real(real_image_pair, strict, iou_threshold):
78 | """Test a real image pair."""
79 | y_true, y_pred = real_image_pair
80 | result = umetrix.calculate(
81 | y_true, y_pred, strict=strict, iou_threshold=iou_threshold
82 | )
83 | assert result.n_true_labels == 13
84 | assert result.n_pred_labels == 14
85 |
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import numpy as np
3 | import numpy.typing as npt
4 |
5 | from pathlib import Path
6 | from skimage.io import imread
7 | from skimage.util import montage
8 | from typing import Tuple
9 |
10 | from umetrix.core import IoU
11 |
12 | SEED = 12343
13 | RNG = np.random.default_rng(seed=SEED)
14 |
15 |
16 | def _synthetic_image(sz: int = 32) -> npt.NDArray:
17 | image = np.zeros((sz, sz), dtype=np.uint8)
18 | boxsz = RNG.integers(low=sz // 4, high=sz - 1)
19 | xlo, ylo = RNG.integers(low=1, high=sz - boxsz, size=(2,))
20 | image[xlo : xlo + boxsz, ylo : ylo + boxsz] = 1
21 | return image
22 |
23 |
24 | # def _IoU(y_true: npt.NDArray, y_pred: npt.NDArray) -> float:
25 | # union = np.sum(np.logical_or(y_true, y_pred))
26 | # intersection = np.sum(np.logical_and(y_true, y_pred))
27 | # return intersection / union
28 |
29 |
30 | @pytest.fixture
31 | def image_grid(N: int = 3, sz: int = 32) -> Tuple[npt.NDArray, npt.NDArray, dict]:
32 | image_types = RNG.choice(
33 | ["pair", "missing_true", "missing_pred"], size=(N * N,)
34 | ).tolist()
35 | true_stack = np.zeros((N * N, sz, sz), dtype=np.uint8)
36 | pred_stack = np.zeros((N * N, sz, sz), dtype=np.uint8)
37 |
38 | ious = []
39 |
40 | n_true_positive = 0
41 | n_false_positive = 0
42 | n_false_negative = 0
43 |
44 | for idx, img_type in enumerate(image_types):
45 | if img_type == "pair":
46 | true_stack[idx, ...] = _synthetic_image()
47 | pred_stack[idx, ...] = _synthetic_image()
48 | iou = IoU(true_stack[idx, ...], pred_stack[idx, ...])
49 | ious.append(iou)
50 | if iou > 0:
51 | n_true_positive += 1
52 | else:
53 | n_false_positive += 1
54 | n_false_negative += 1
55 | elif img_type == "missing_true":
56 | pred_stack[idx, ...] = _synthetic_image()
57 | ious.append(0.0)
58 | n_false_positive += 1
59 | else:
60 | true_stack[idx, ...] = _synthetic_image()
61 | ious.append(0.0)
62 | n_false_negative += 1
63 |
64 | # number of pairs where there is some overlap
65 | n_pairs = image_types.count("pair")
66 | n_missing_true = image_types.count("missing_true")
67 | n_missing_pred = image_types.count("missing_pred")
68 |
69 | stats = {
70 | "n_pairs": n_pairs,
71 | "n_true": n_pairs + n_missing_pred,
72 | "n_pred": n_pairs + n_missing_true,
73 | "n_true_positive": n_true_positive,
74 | "n_false_positive": n_false_positive,
75 | "n_false_negative": n_false_negative,
76 | "n_total": len(image_types),
77 | "IoU": ious,
78 | }
79 |
80 | return (
81 | montage(true_stack, rescale_intensity=False, grid_shape=(N, N)),
82 | montage(pred_stack, rescale_intensity=False, grid_shape=(N, N)),
83 | stats,
84 | )
85 |
86 |
87 | @pytest.fixture
88 | def image_pair() -> Tuple[npt.NDArray, npt.NDArray, dict]:
89 | y_true = _synthetic_image()
90 | y_pred = _synthetic_image()
91 | stats = {"IoU": IoU(y_true, y_pred)}
92 | return y_true, y_pred, stats
93 |
94 |
95 | @pytest.fixture
96 | def real_image_pair() -> Tuple[npt.NDArray, npt.NDArray]:
97 | filename = Path(__file__).parent.resolve() / "data" / "unet.tif"
98 | img = (imread(filename) > 0).astype(np.uint8)
99 | return img[0, ...], img[1, ...]
100 |
--------------------------------------------------------------------------------
/src/umetrix/render.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 | import matplotlib.patches as patches
4 |
5 |
6 | def plot_metrics(seg_metrics):
7 | pred = seg_metrics._predicted
8 | ref = seg_metrics._reference
9 |
10 | iou = [None] * len(ref.labels)
11 | IoU = seg_metrics.per_object_IoU
12 | for i, tp in enumerate(seg_metrics.true_positives):
13 | iou[tp[0] - 1] = "{:.2f}".format(IoU[i])
14 |
15 | fig, ax = plt.subplots(1, figsize=(16, 12))
16 | ax.imshow(seg_metrics.image_overlay)
17 |
18 | for i, (sy, sx) in enumerate(ref.bboxes):
19 | r = patches.Rectangle(
20 | (sx.start, sy.start),
21 | sx.stop - sx.start,
22 | sy.stop - sy.start,
23 | edgecolor="g",
24 | facecolor="None",
25 | )
26 | ax.add_patch(r)
27 | ax.text(
28 | sx.start, sy.start, "{}, IoU: {}".format(i, iou[i]), fontsize=6, color="w"
29 | )
30 | for i, (sy, sx) in enumerate(pred.bboxes):
31 | r = patches.Rectangle(
32 | (sx.start, sy.start),
33 | sx.stop - sx.start,
34 | sy.stop - sy.start,
35 | edgecolor="m",
36 | facecolor="None",
37 | )
38 | ax.add_patch(r)
39 | # ax.text(sx.start, sy.start, '{}'.format(i), fontsize=6, color='w')
40 |
41 | bboxes = pred.bboxes
42 | for fp in seg_metrics.false_positives:
43 | sy, sx = bboxes[fp - 1]
44 | w, h = sx.stop - sx.start, sy.stop - sy.start
45 | r = patches.Rectangle(
46 | (sx.start, sy.start),
47 | w,
48 | h,
49 | edgecolor="r",
50 | facecolor=(1.0, 0.0, 0.0, 0.0),
51 | linewidth=2,
52 | )
53 | ax.add_patch(r)
54 |
55 | bboxes = ref.bboxes
56 | for fn in seg_metrics.false_negatives:
57 | sy, sx = bboxes[fn - 1]
58 | w, h = sx.stop - sx.start, sy.stop - sy.start
59 | r = patches.Rectangle(
60 | (sx.start, sy.start),
61 | w,
62 | h,
63 | edgecolor="c",
64 | facecolor=(0.0, 1.0, 1.0, 0.0),
65 | linewidth=2,
66 | )
67 | ax.add_patch(r)
68 | plt.axis("off")
69 | plt.show()
70 |
71 |
72 | def make_bboxes(bbox_slices):
73 | """Calculate bboxes for napari"""
74 | minr = [sxy[0].start for sxy in bbox_slices]
75 | minc = [sxy[1].start for sxy in bbox_slices]
76 | maxr = [sxy[0].stop for sxy in bbox_slices]
77 | maxc = [sxy[1].stop for sxy in bbox_slices]
78 |
79 | bbox_rect = np.array([[minr, minc], [maxr, minc], [maxr, maxc], [minr, maxc]])
80 | bbox_rect = np.moveaxis(bbox_rect, 2, 0)
81 | return bbox_rect
82 |
83 |
84 | def render_metrics_napari(seg_metrics):
85 | """Render the segmentation metrics for visualization in Napari."""
86 |
87 | # pred = seg_metrics._predicted
88 | ref = seg_metrics._reference
89 |
90 | properties = {"iou": seg_metrics.per_object_IoU}
91 |
92 | bboxes = make_bboxes(ref.bboxes)
93 | tp_idx = np.asarray(seg_metrics.true_positives)[:, 0] - 1
94 | bboxes = bboxes[tp_idx, ...]
95 |
96 | # specify the display parameters for the text
97 | text_parameters = {
98 | "text": "IoU: {iou:.2f}\n",
99 | "size": 8,
100 | "color": "white",
101 | "anchor": "upper_left",
102 | "translation": [-2, 0],
103 | }
104 |
105 | return bboxes, properties, text_parameters
106 |
--------------------------------------------------------------------------------
/src/umetrix/notebooks.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import io
3 | import itertools
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 |
7 | from matplotlib import colors, colormaps
8 |
9 | from umetrix.core import METRICS
10 |
11 |
12 | DARK_CONTEXT = {
13 | "axes.edgecolor": "gray",
14 | "xtick.color": "gray",
15 | "ytick.color": "gray",
16 | "axes.labelcolor": "gray",
17 | "font.size": 18,
18 | }
19 |
20 |
21 | def _text_color_based_on_value(value: float, cmap: colors.Colormap) -> str:
22 | rgb = cmap(value)
23 | luminance = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]
24 | return "k" if luminance > 0.5 else "w"
25 |
26 |
27 | def _header() -> str:
28 | css = (
29 | ".row {display: inline-flex; align-items: flex-start;}\n"
30 | ".metrics {float: left;}\n"
31 | ".confusion {width: 200px; float: left;}"
32 | )
33 | return f"
"
34 |
35 |
36 | def _footer() -> str:
37 | return ""
38 |
39 |
40 | def render_metrics_html(metrics) -> str:
41 | """Render the metrics to HTML"""
42 |
43 | html_table = _render_table(metrics)
44 | encoded_cm = _render_confusion(metrics)
45 | html_strict = (
46 | f"Strict matching (IoU threshold: {metrics.iou_threshold})
"
47 | if metrics.strict
48 | else ""
49 | )
50 |
51 | html = (
52 | _header()
53 | + "Segmentation Metrics
"
54 | + html_strict
55 | + ""
56 | + html_table
57 | + "
"
58 | + f"

"
59 | + "
"
60 | + _footer()
61 | )
62 |
63 | return html
64 |
65 |
66 | def _render_table(metrics) -> str:
67 | """Render the table of results"""
68 |
69 | def _get_f_string(m):
70 | val = getattr(metrics, m)
71 | return f"{val:.3f}" if isinstance(val, float) else f"{val:d}"
72 |
73 | return (
74 | "| Metric | |
"
75 | + "".join(
76 | [f"| {m} | " + _get_f_string(m) + " |
" for m in METRICS]
77 | )
78 | + "
"
79 | )
80 |
81 |
82 | def _render_confusion(metrics, *, cmap: str = "Blues") -> str:
83 | """Render a confusion matrix as an image"""
84 | grid = np.zeros((2, 2), dtype=float)
85 | grid[1, 1] = metrics.n_true_positives
86 | grid[0, 1] = metrics.n_false_positives
87 | grid[1, 0] = metrics.n_false_negatives
88 | cmap = colormaps[cmap]
89 |
90 | with plt.rc_context(DARK_CONTEXT):
91 | _, ax = plt.subplots(figsize=(4, 4))
92 | ax.pcolor(grid, cmap=cmap)
93 | ax.set_xticks([0.5, 1.5], labels=["Negative", "Positive"])
94 | ax.set_yticks(
95 | [0.5, 1.5], labels=["Negative", "Positive"], rotation=90, va="center"
96 | )
97 |
98 | for i, j in itertools.product(range(2), range(2)):
99 | ax.text(
100 | i + 0.5,
101 | j + 0.5,
102 | grid[i, j].astype(int),
103 | ha="center",
104 | va="center",
105 | color=_text_color_based_on_value(grid[i, j] / np.max(grid), cmap),
106 | )
107 | ax.set_ylabel("Predicted")
108 | ax.set_xlabel("Ground truth")
109 | stream = io.BytesIO()
110 | plt.savefig(stream, format="png", bbox_inches="tight", transparent=True)
111 | plt.close()
112 | return base64.b64encode(stream.getvalue()).decode("utf-8")
113 |
--------------------------------------------------------------------------------
/src/umetrix/core.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import enum
4 | import numpy as np
5 | import numpy.typing as npt
6 |
7 | from skimage.io import imread
8 | from scipy.ndimage import label
9 | from scipy.ndimage import center_of_mass
10 | from scipy.ndimage import find_objects
11 | from scipy.optimize import linear_sum_assignment
12 |
13 | from typing import Dict, Tuple
14 |
15 | from umetrix import render
16 |
17 |
18 | DEFAULT_MAXIMUM_COST = 1e8
19 |
20 |
21 | class Metrics(str, enum.Enum):
22 | N_TRUE_LABELS = "n_true_labels"
23 | N_PRED_LABELS = "n_pred_labels"
24 | N_TRUE_POSITIVES = "n_true_positives"
25 | N_FALSE_POSITIVES = "n_false_positives"
26 | N_FALSE_NEGATIVES = "n_false_negatives"
27 | IOU = "IoU"
28 | JACCARD = "Jaccard"
29 | PIXEL_IDENTITY = "pixel_identity"
30 | LOCALIZATION_ERROR = "localization_error"
31 |
32 |
33 | METRICS = (
34 | "n_true_labels",
35 | "n_pred_labels",
36 | "n_true_positives",
37 | "n_false_positives",
38 | "n_false_negatives",
39 | "IoU",
40 | "Jaccard",
41 | "pixel_identity",
42 | "localization_error",
43 | )
44 |
45 |
46 | def IoU(ref: npt.NDArray, pred: npt.NDArray) -> float:
47 | """Calculate the IoU between two binary masks."""
48 | intersection = np.sum(np.logical_and(ref, pred))
49 | union = np.sum(np.logical_or(ref, pred))
50 | iou = 0.0 if union == 0 else intersection / union
51 | return iou
52 |
53 |
54 | def find_matches(
55 | ref: LabeledSegmentation,
56 | pred: LabeledSegmentation,
57 | *,
58 | strict: bool = False,
59 | iou_threshold: float = 0.5,
60 | ) -> Dict:
61 | """Perform matching between the reference and the predicted image.
62 |
63 | Parameters
64 | ----------
65 | ref :
66 | The reference (ground truth) segmentation.
67 | pred :
68 | The predicted segmentation.
69 | strict : bool
70 | Whether to use strict matching, i.e. only allowing matches above a
71 | threshold IoU value.
72 | iou_threshold :
73 | A threshold value to use when strict matching.
74 |
75 | Return
76 | ------
77 | matches : dict
78 | A dictionary of matches between the two images.
79 | """
80 |
81 | # make an infinite cost matrix, so that we only consider matches where
82 | # there is some overlap in the masks
83 | cost_matrix = np.full((len(ref.labels), len(pred.labels)), DEFAULT_MAXIMUM_COST)
84 |
85 | for r_id, ref_label in enumerate(ref.labels):
86 | mask = ref.labeled == ref_label
87 | _matches = [m for m in np.unique(pred.labeled[mask]) if m > 0]
88 | for pred_label in _matches:
89 | p_id = pred.labels.index(pred_label)
90 | reward = IoU(mask, pred.labeled == pred_label)
91 | if (reward < iou_threshold) and strict:
92 | continue
93 | cost_matrix[r_id, p_id] = 1.0 - reward
94 |
95 | # if it's strict, make sure every element is above the threshold
96 | if strict:
97 | cost_threshold = 1.0 - iou_threshold
98 | cost_mask = cost_matrix == DEFAULT_MAXIMUM_COST
99 | assert np.all(cost_matrix[~cost_mask] <= cost_threshold)
100 |
101 | # solve it using JV
102 | sol_row, sol_col = linear_sum_assignment(cost_matrix)
103 |
104 | # remove infeasible solutions
105 | edges = [
106 | (ref.labels[r], pred.labels[c], 1.0 - cost_matrix[r, c])
107 | for r, c in zip(sol_row, sol_col)
108 | if cost_matrix[r, c] <= 1
109 | ]
110 |
111 | # return a default dictionary if there are no matches
112 | if not edges:
113 | matches = {
114 | "true_matches": [],
115 | "true_matches_IoU": [],
116 | "in_ref_only": set(ref.labels),
117 | "in_pred_only": set(pred.labels),
118 | }
119 | return matches
120 |
121 | # find the labels that haven't been used
122 | used_ref, used_pred, IoUs = zip(*edges)
123 | in_ref_only = set(ref.labels).difference(used_ref)
124 | in_pred_only = set(pred.labels).difference(used_pred)
125 |
126 | # return a dictionary of found matches
127 | matches = {
128 | "true_matches": list(set(zip(used_ref, used_pred))),
129 | "true_matches_IoU": IoUs,
130 | "in_ref_only": in_ref_only,
131 | "in_pred_only": in_pred_only,
132 | }
133 |
134 | return matches
135 |
136 |
137 | class MetricResults(object):
138 | def __init__(self, metrics):
139 | assert isinstance(metrics, SegmentationMetrics)
140 | self._images = 1
141 | self._metrics = metrics
142 |
143 | # list of metrics that are aggregated
144 | self._agg = (
145 | "n_true_labels",
146 | "n_pred_labels",
147 | "n_true_positives",
148 | "n_false_positives",
149 | "n_false_negatives",
150 | "per_object_IoU",
151 | "per_object_localization_error",
152 | "per_image_pixel_identity",
153 | )
154 |
155 | def __getattr__(self, key):
156 | return getattr(self._metrics, key)
157 |
158 | @property
159 | def n_images(self) -> int:
160 | if any([getattr(self, m) is None for m in self._agg]):
161 | return 0
162 | else:
163 | return self._images
164 |
165 | def __add__(self, result: MetricResults) -> MetricResults:
166 | assert isinstance(result, MetricResults)
167 | for m in self._agg:
168 | setattr(self, m, getattr(result, m) + getattr(self, m))
169 | self._images += 1
170 | return self
171 |
172 | def __repr__(self) -> str:
173 | title = f" Segmentation Metrics (n={self.n_images})\n"
174 | hbar = "=" * len(title) + "\n"
175 | r = hbar + title + hbar
176 | if self.strict:
177 | r += f"Strict: {self.strict} (IoU > {self.iou_threshold})\n"
178 | for m in METRICS:
179 | mval = getattr(self, m)
180 | if isinstance(mval, float):
181 | r += f"{m}: {mval:.3f}\n"
182 | else:
183 | r += f"{m}: {mval}\n"
184 | return r
185 |
186 | def _repr_html_(self):
187 | from umetrix.notebooks import render_metrics_html
188 |
189 | return render_metrics_html(self)
190 |
191 | @property
192 | def localization_error(self) -> float:
193 | return np.mean(self.per_object_localization_error)
194 |
195 | @property
196 | def IoU(self) -> float:
197 | return np.mean(self.per_object_IoU)
198 |
199 | @property
200 | def Jaccard(self) -> float:
201 | """Jaccard metric"""
202 | tp = self.n_true_positives
203 | fn = self.n_false_negatives
204 | fp = self.n_false_positives
205 | return tp / (tp + fn + fp)
206 |
207 | @property
208 | def pixel_identity(self) -> float:
209 | return np.mean(self.per_image_pixel_identity)
210 |
211 | @staticmethod
212 | def merge(results: list) -> MetricResults:
213 | """Merge n results together and return a single object."""
214 | merged = results.pop(0)
215 | for result in results:
216 | assert isinstance(result, MetricResults)
217 | assert result.n_images == 1
218 | merged = merged + result
219 | return merged
220 |
221 |
222 | class SegmentationMetrics:
223 | """A class for calculating various segmentation metrics to assess the
224 | accuracy of a trained model.
225 |
226 | Parameters
227 | ----------
228 | reference : array
229 | An array containing labeled objects from the ground truth.
230 | predicted : array
231 | An array containing labeled objects from the segmentation algorithm.
232 | strict : bool
233 | Whether to disregard matches with a low IoU score.
234 | iou_threshold : float
235 | Threshold IoU for strict matching.
236 |
237 | Properties
238 | ----------
239 | Jaccard : float
240 | The Jaccard index calculated according to the notes below.
241 | IoU : float
242 | The Intersection over Union metric.
243 | localisation_precision : float
244 | The localisation precision.
245 | true_positives : int
246 | Number of TP predictions.
247 | false_positives : int
248 | Number of FP predictions.
249 | false_negatives : int
250 | Number of FN predicitons.
251 |
252 |
253 | Notes
254 | -----
255 | The Jaccard metric is calculated accordingly:
256 |
257 | FP = number of objects in predicted but not in reference
258 | TP = number of objects in both
259 | TN = background correctly segmented (not used)
260 | FN = number of objects in true but not in predicted
261 |
262 | J = TP / (TP+FP+FN)
263 |
264 | The IoU is calculated as the intersection of the binary segmentation
265 | divided by the union.
266 | """
267 |
268 | def __init__(
269 | self, reference: LabeledSegmentation, predicted: LabeledSegmentation, **kwargs
270 | ):
271 | assert isinstance(predicted, LabeledSegmentation)
272 | assert isinstance(reference, LabeledSegmentation)
273 |
274 | self._reference = reference
275 | self._predicted = predicted
276 | self._strict = kwargs.get("strict", False)
277 | self._iou_threshold = kwargs.get("iou_threshold", 0.5)
278 |
279 | if self.iou_threshold < 0.0 or self.iou_threshold > 1.0:
280 | raise ValueError(
281 | f"IoU Threshold shoud be in (0, 1), found: {self.iou_threshold:.2f}"
282 | )
283 | assert isinstance(self.strict, bool)
284 |
285 | # find the matches
286 | self._matches = find_matches(
287 | self._reference,
288 | self._predicted,
289 | strict=self.strict,
290 | iou_threshold=self.iou_threshold,
291 | )
292 |
293 | @property
294 | def strict(self) -> bool:
295 | return self._strict
296 |
297 | @property
298 | def iou_threshold(self) -> float:
299 | return self._iou_threshold
300 |
301 | @property
302 | def results(self):
303 | return MetricResults(self)
304 |
305 | @property
306 | def image_overlay(self):
307 | # n_labels = max([self._predicted.n_labels, self._reference.n_labels])
308 | # scale = int(255 / n_labels)
309 | return (
310 | np.stack(
311 | [self._predicted.image, self._reference.image, self._predicted.image],
312 | axis=-1,
313 | )
314 | * 127
315 | )
316 |
317 | @property
318 | def n_true_labels(self):
319 | return self._reference.n_labels
320 |
321 | @property
322 | def n_pred_labels(self):
323 | return self._predicted.n_labels
324 |
325 | @property
326 | def true_positives(self):
327 | """Only one match between reference and predicted."""
328 | return self._matches["true_matches"]
329 |
330 | @property
331 | def false_negatives(self):
332 | """No match in predicted for reference object."""
333 | return self._matches["in_ref_only"]
334 |
335 | @property
336 | def false_positives(self):
337 | """Combination of non unique matches and unmatched objects."""
338 | return self._matches["in_pred_only"]
339 |
340 | @property
341 | def n_true_positives(self):
342 | return len(self.true_positives)
343 |
344 | @property
345 | def n_false_negatives(self):
346 | return len(self.false_negatives)
347 |
348 | @property
349 | def n_false_positives(self):
350 | return len(self.false_positives)
351 |
352 | @property
353 | def per_object_IoU(self):
354 | """Intersection over Union (IoU) metric"""
355 | return self._matches["true_matches_IoU"]
356 |
357 | @property
358 | def per_image_pixel_identity(self):
359 | """Calculate the per-image pixel identity."""
360 | n_tot = np.prod(self._reference.image.shape)
361 | return [np.sum(self._reference.image == self._predicted.image) / n_tot]
362 |
363 | @property
364 | def per_object_localization_error(self):
365 | """Calculate the per-object localization error."""
366 | ref_centroids = self._reference.centroids
367 | tgt_centroids = self._predicted.centroids
368 | positional_error = []
369 | for m in self.true_positives:
370 | true_centroid = np.array(ref_centroids[m[0] - 1])
371 | pred_centroid = np.array(tgt_centroids[m[1] - 1])
372 | err = np.sum((true_centroid - pred_centroid) ** 2)
373 | positional_error.append(err)
374 | return positional_error
375 |
376 | def plot(self):
377 | render.plot_metrics(self)
378 |
379 | def to_napari(self):
380 | return render.render_metrics_napari(self)
381 |
382 | def __repr__(self):
383 | return self.results.__repr__()
384 |
385 | def _repr_html_(self):
386 | return self.results._repr_html_()
387 |
388 |
389 | class LabeledSegmentation:
390 | """A helper class to enable simple calculation of accuracy statistics for
391 | image segmentation output.
392 | """
393 |
394 | def __init__(self, image: npt.NDArray):
395 | self.image = image
396 | self.labeled, self.n_labels = label(image.astype(bool))
397 |
398 | @property
399 | def shape(self) -> Tuple[int]:
400 | return self.image.shape
401 |
402 | @property
403 | def bboxes(self):
404 | return [find_objects(self.labeled == label)[0] for label in self.labels]
405 |
406 | @property
407 | def labels(self):
408 | return range(1, self.n_labels + 1)
409 |
410 | @property
411 | def centroids(self):
412 | return [center_of_mass(self.labeled == label) for label in self.labels]
413 |
414 | @property
415 | def areas(self):
416 | return [np.sum(self.labeled == label) for label in self.labels]
417 |
418 |
419 | def calculate(reference, predicted, **kwargs):
420 | """Take a predicted image and compare with the reference image.
421 |
422 | Compute various metrics.
423 | """
424 |
425 | ref = LabeledSegmentation(reference)
426 | tgt = LabeledSegmentation(predicted)
427 |
428 | # make sure they are the same size
429 | assert ref.shape == tgt.shape
430 |
431 | return SegmentationMetrics(ref, tgt, **kwargs)
432 |
433 |
434 | def batch(files, **kwargs):
435 | """batch process a list of files"""
436 | metrix = []
437 | for f_ref, f_pred in files:
438 | true = imread(f_ref)
439 | pred = imread(f_pred)
440 | result = calculate(true, pred, **kwargs).results
441 | metrix.append(result)
442 | return MetricResults.merge(metrix)
443 |
444 |
445 | if __name__ == "__main__":
446 | pass
447 |
--------------------------------------------------------------------------------
/notebooks/unet_segmentation_metrics.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "## Simple demonstration of calculating segmentation metrics"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "*NOTE(arl)*: the metrics here are calculated as follows in batch mode:\n",
15 | "+ `n_true_labels` is the sum of all true labels, etc\n",
16 | "+ `IoU` is the mean IoU of all found objects\n",
17 | "+ `Jaccard` is the Jaccard index over all found objects\n",
18 | "+ `localization_error` is the mean error for all found objects\n",
19 | "+ `pixel_identity` is the per image pixel identity"
20 | ]
21 | },
22 | {
23 | "cell_type": "code",
24 | "execution_count": 1,
25 | "metadata": {},
26 | "outputs": [],
27 | "source": [
28 | "import umetrix\n",
29 | "\n",
30 | "import numpy as np\n",
31 | "from skimage.io import imread"
32 | ]
33 | },
34 | {
35 | "cell_type": "code",
36 | "execution_count": 2,
37 | "metadata": {},
38 | "outputs": [],
39 | "source": [
40 | "# load a ground truth - prediction image pair\n",
41 | "p = \"../tests/data/unet.tif\"\n",
42 | "s = imread(p)\n",
43 | "y_true = s[-2, ...]\n",
44 | "y_pred = s[-1, ...]"
45 | ]
46 | },
47 | {
48 | "cell_type": "code",
49 | "execution_count": 3,
50 | "metadata": {},
51 | "outputs": [],
52 | "source": [
53 | "result = umetrix.calculate(y_true, y_pred)"
54 | ]
55 | },
56 | {
57 | "cell_type": "code",
58 | "execution_count": 4,
59 | "metadata": {},
60 | "outputs": [
61 | {
62 | "data": {
63 | "text/html": [
64 | "Segmentation Metrics
| Metric | |
|---|
| n_true_labels | 13 |
| n_pred_labels | 14 |
| n_true_positives | 12 |
| n_false_positives | 2 |
| n_false_negatives | 1 |
| IoU | 0.807 |
| Jaccard | 0.800 |
| pixel_identity | 0.959 |
| localization_error | 15.524 |
"
67 | ],
68 | "text/plain": [
69 | "============================\n",
70 | " Segmentation Metrics (n=1)\n",
71 | "============================\n",
72 | "n_true_labels: 13\n",
73 | "n_pred_labels: 14\n",
74 | "n_true_positives: 12\n",
75 | "n_false_positives: 2\n",
76 | "n_false_negatives: 1\n",
77 | "IoU: 0.807\n",
78 | "Jaccard: 0.800\n",
79 | "pixel_identity: 0.959\n",
80 | "localization_error: 15.524"
81 | ]
82 | },
83 | "execution_count": 4,
84 | "metadata": {},
85 | "output_type": "execute_result"
86 | }
87 | ],
88 | "source": [
89 | "result"
90 | ]
91 | },
92 | {
93 | "cell_type": "markdown",
94 | "metadata": {},
95 | "source": [
96 | "## visualize the metrics"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": 5,
102 | "metadata": {},
103 | "outputs": [
104 | {
105 | "data": {
106 | "image/png": "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7a688spccsklefDBBzfqo6amJpdccklOOeWUJMnUqVNz8MEHp66u9Pl6jz32yPe///0MHz48s2fPzve///0Nth966KG55JJL0tramptuuikXXnhh9txzz/z26t+malBVHvnZI5l/2fyy7+PyLC+7bV9wek7fpts51wJQJIo4AfQzQ4YMyac//em8973vzZFHHpnf/Ow3PbLf888/PxdffHEOP/zwnH322Rk6dOgG288777yceeaZede73pWjjz461dXVueCCC/K7//hdrj7y6tQcUZOdxu3UI2MFAHonARagn3nXu96V5ubm/PznP8/111+f0buP3uJtBg4cmGuuuSa33357brzxxuy8886bbX/55ZdvFFAnTZqUW2+9NevWrcu9996b/fbbb4PtDz30UKqrqzNo0KCsW7cuq1atyt57753n/vRckqTxz415w+Q3bOW9BQD6EgEWoJ/Zfffd86Y3vSnHHXdc5syZk3O+cM4Wb3PCCSfkqaeeypFHHpkf/vCHOeeczd/m3HPPzapVqza4btCgQWlra0uSNDU1ZZdddtlg+w033JB58+bl4Ycfzu23357Vq1dn4cKFeeO735gBAwek5siaDB21YSgGAPqX3rEGtsRyKWte+5BSD6UlV1Axy5Yty+9+97usWbMmt956ay684MKsyIrN3mbChAlZsGBBkmTBggU55phjsmrVqgwZMqSjzdChQ9Pc3LzJPtasWZOqqqq0trZm1KhRefHFFzc415916Vm5/rDrs2zRsvzjvH/MbvvulpVfWpm3zX5b3vmxd+blp1/O8uc2sa61v71kdOE5tJzXW+tkAegtzMAC9DP/7//9v7z1rW9Nkhx44IF5+vGnkyS7j9t9k7d57LHHMmnSpCTtHwVuaGjIkiVLMn78+Awb1v71O4ceemgeeOCBTfZx7733ZsqUKRk4cGAOOuig/M///M8G29ta27KqaVXSlqx+ZXWGVA/JyqUrc+3J1+YH7/1BqgZX5cnbn9yeuw4AFFzvmIEFoMe8uO7F/OyOn+WOe+5Ia2tr/v0T/57P5XP56n99NUecfkRaWlpeazwsyW7JDb+/ISeedmLuuOeOrFi5Iqf982nJ2ORzl38ut9x5S1paWvLQow/ll3/6ZTI2ubzu8lzwpQs2+BjxxVdenLnfmJsLL74w3/ret7J6l9Wp2q8qex+0d+783p25/j+vz8k3n5zWda1Z8pclWfDUgrz1Q2/N1I9PTVtrW379zV9n0chFycgSd6qt2w9b7zK20gPYSiuTNFV6EAD0BQIsQH9SneTjyTd3+Ga++atvJkkmHjQxuS95Yt0TaTmrZYPmZz18VnJkkiOT0/58WvLn9Rv+sf3HL/KL/OLGX7x2gxntP85dfG5y5oa7fi7P5ahbj2q/sGt728/lcxve7hfnbtRXbln/c9/1//PasSmKliRXRIgFYLsJsAD9yfAkOySZl2Tp+uvWJGlNak+uTQb37HBmdFUSK1qg2171Pb277djh6CQnpf25J8ACsJ16PsD2t0IbAL3R0iTPlriuG5VVnM9rRHlmbuPttrEWk0JPAPQWijgBAABQCAIsAAAAhSDAAgAAUAgCLAAAAIXQK6oQl1XYA4DCKPu87vTfs8o53l1Y6ElhJwC6mhlYAAAACkGABQAAoBAEWAAAAAqh+9fA1nW+aMETQL/k9F8MpR4nS1kB6CXMwAIAAFAIAiwAAACFIMACAABQCAIsAAAAhdC1RZxeLfywOEl9khld2jsAvdRGBfoUbOpbOj+eijoBUCFmYAEAACgEARYAAIBCEGABAAAoBAEWAACAQujaIk4lbFTYA4C+x6m+fyn1eJco7FSXuizO4tSnPjMyI/Wp7/ahAdC3mYEFAACgEARYAAAACkGABQAAoBC6fQ0sAH1LXZ0Fr5RQ5rpYANgeZmABAAAoBAEWAACAQhBgAQAAKAQBFgAAgELYviJOdZ0vtl8xIiOSJDMzM8uzfLt2AQAUU+3rqjjVp76CIwGgrzADCwAAQCEIsAAAABSCAAsAAEAhbN8aWAD6tLq6ui03AgDoIWZgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCKL+IU12StvW/z0gyoDuGAwAAAKWZgQUAAKAQBFgAAAAKQYAFAACgEARYAAAACqH8Ik7QjWpTW+khAEnq6uoqPQQKqrbWeRyA7mcGFgAAgEIQYAEAACgEARYAAIBCsAYWANgq6hYAUClmYAEAACgEARYAAIBCEGABAAAoBAEWAACAQlDECaC/qlv/c3GS+iQzKjgWerWNijap4QRAhZiBBQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKQREngH6qbn0VpxEZkSSZmZlZnuWVHBK9wEYFm9qvBIBewQwsAAAAhSDAAgAAUAgCLAAAAIVgDSzdr+RyqteurE99Dw4GgNfbaM2r9a4A9GJmYAEAACgEARYAAIBCEGABAAAoBAEWAACAQlDECaC/qEvStv73GZUcCD1ho+JMm24IAIVhBhYAAIBCEGABAAAoBAEWAACAQujSNbCvrreZmImZkzmZndk5Pad35S4ogtrOFy2wAuhKZZ1XnXoB6IPMwAIAAFAIAiwAAACFIMACAABQCAIsAAAAhVB+EafaJGOTzEhSn+TZJHXdMygA6K8UaAKATTMDCwAAQCEIsAAAABSCAAsAAEAhCLAAAAAUQvlFnLZR52IUdSo/9S0lComUVYAEgNLnS6dQANgkM7AAAAAUggALAABAIQiwAAAAFML2rYHtvE7H8lYASJLU1lrMCgBdzQwsAAAAhSDAAgAAUAgCLAAAAIUgwAIAAFAI21fEaRuU+tL2OtWfiqFEPZJSjydAf6NgEwD0DDOwAAAAFIIACwAAQCEIsAAAABRC166B7bwEqD4pZ3mrdbG9VG3ni9Z4Af1PyXOf0yEAVIQZWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgELq2iFMpnQtdlFmbqXPRDEWdulnJGiWqlAD9kFMfAPRaZmABAAAoBAEWAACAQhBgAQAAKAQBFgAAgELo/iJOnZUqjlFGfaZSBYUUduo6CjZB//Pq3/3ETMyczMnszM7pOb3Co+phCtgBQKGYgQUAAKAQBFgAAAAKQYAFAACgEHp+DWwpXbguduNurJOtrbWeC0j7uXZskhlJ6pPMrOxweppzIQAUnxlYAAAACkGABQAAoBAEWAAAAApBgAUAAKAQekcRp1I619rYxlpMfb3Q00b3T40SoFydzxf1SW3dhlcW+vyoaBMA9DlmYAEAACgEARYAAIBCEGABAAAoBAEWAACAQui9RZw6K7cWxzbUGymn0FOvUJBhAgXWuS5cXXknnp4s9qQ4EwD0X90aYGtS053dl7a453fJNlqT9sdrzaabVOQ5BAAA9ErdEmCb0pTmNGdWZnVH95tX3/O7ZBstTTJny82a05ymNHX7cAAAgN6tWwJsYxozLdNSneru6H7zZvT8LntMXwvno5OcmOT6tIfZTWhKUxrT2EODAgAAeqtu+whx4/r/elxXhbyuXM5luVZpg5OMW/8T6J3KPH+Vu1Z2W/sHAEhUIQYAAKAgilOFGIButV1F0xTQY1NKFOxToA+AbSXAAvRzXVJ4r6+t0afrbKJgnwJ9AGwLARagn+uSwnvbWkBP8O37NlGwT4E+ALaFALspCosA/ch2F94TRNkUBfsA6ELbFmBHd/Eo6J88j6By/P3RUzzXAOhCWxdgVyZpSXJSt4yF/qgl7c8roGc4j1MJzvUAdJEBbW1tbWU1HDCg/ZfqJMO7cUT0LysTNTyghzmP09Oc6wHYgjJj6TYEWAAAAOhC5QbYqm4eBwAAAHQJARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCGFTpAQAA0D3qUlfR/demtqL7B/oeM7AAQL8zadKk3Hbbbbntttvy8MMP57LLLttk2yuvvDL77bdfyW01NTW59tprOy5PnTo1tbWbDm177LFHbr755tx1110544wzNtp+6KGHZv78+bn77rvz+c9/Pkly5pln5tFHH81tt92WuXPnlnsXAfokM7AAQL+zYMGCTJkyJUny7W9/OzfccENZtxuTMalOdcflPbNnRmREJmZix+Vds2vH5c5mnT8rcy+em9/f/vv84Lc/yH3X3pfVq1Z3bP/CeV9I7Zm1efyRx/PD3/4wv/jaL7J7ds8Pv/bDzL2iPbxuqu9SRmRE2W27w9aMtbs1pSmNaaz0MIDtJMACAP3WwIEDc/DBB2f69OlbbDt24Njc+717M3zP4Vm3Yl0Wnr4wgzIoEzIhczInSbJLdsnIjMzb8/a8+fI35/ELHk/rqtaOPg6cdGBqzq3JtLZp2e3e3XLVflfllT+80rF974f2zkXVF2X5oOWZsG5CLl91ecZkTMb/0/h84h8/kcVXLE7jfxUnhL16XHqD5jRnWqYJsVBwAiwA0G+9+93vzh133JG2trYttj35hJOz9qm1OeW0U3LA6Qdk/Dnj85Orf5LP5rP5RD6RJDksh+WAHJBv5BvJuRv3cd2g6zK9rT0sf7Lpk1mwy4Lclbs6tu9/w/75xrxvpGV1S+bOnZuvr/56drphpyz/3vIM33F4rv7N1Zl1x6w8/9zzZd2/mZlZVrvuMjuzK7r/V9WkJrMyK9WpFmCh4ARYAKDfOuWUU3LNNdeU1XavCXvl5QUvZ1EW5ekFT2fWMbOycNXCrBmyJg1pSJK8dehb89fmv3Zc7uyVNa/kL1V/SWtra1pHteaBFx/YoO2Vl16ZyYdNzqJFizJv3rwM3Hdg/vjwH1NXV9dx+xlfnpEnn3yyrDEvz/INr+jhmkqn5/QttlHoCdgaAiwA0P9UJwN3GpjJh03OjC/MSMa2Xz1uj3FZ/NziDdsOS7JbsqhxUUZOGpncmUw6elIanmvIkqolGb/3+Azbe1iam5tz6LGH5tbf3drRX2f3Lrw3U06ektvvvj0HHXxQPnPpZzZo2zqoNU3DmtK2R1teWftKqidUZ6d1O2Vx2+IMGDAgu+25W/57wX/nhbYXtu1+b2Jcfd6aJEuTjE4yuMJj6Q4rkzRVehDQMwRYAKB/qU7y8WTKvlNy5yt3pm36ax8fnvuRuTn2mmPTsq7ltfb7JDklueWBW/Jve/1brrn7mizN0px2/WnJjORzf/5cbrn9lrSsa8lDzz+UXy75ZTIxuXzq5bngNxdk1dpVHV1d3HRx5n5pbi4cfGG+de+3snra6uy/+/6ZPH5yZt87O3WP1OW/f/3fWdu6No+88Eh+P+n3+fxnPp/3vvm9GZAB+eb/fDNfa/ratt/3Gdt+00JbnGROkhOTjKvwWLpDS5IrIsTSLwxoK2fRR5IBAwZ091gAALrf2LQHuXlpn5Vbr6qqKlf8xxU5+/yzS95s4pqJmbN0TqaPnp6GwaU/ItxdZszoouRZ3zXddKX6HhhUJR+7bjc6yUlpf2yfrfBYYDuUGUvNwAIA/dTSbPCGvzWtOfvM0uF1o9v1sHEDumjasL8HnAo8dkDXEmABAHpKXamrSlzZg/svSzfWWSr3/iv2BCRJVaUHAAAAAOUQYAEAACgEARYAAIBCsAYWAKA7VHq9a1cqZ9jdvES187GzJhb6JzOwAAAAFIIACwAAQCEIsAAAABSCAAsAAEAhKOIEANAV6jpfLGjBpm1V6u52Y52lUsdXYSfo+8zAAgAAUAgCLAAAAIUgwAIAAFAI1sACAGytEus9+92a13L08LpYoO/r9TOwAwYMyFVXXZU777wzd9xxR/bee+9Ntr3yyiuz3377ldxWU1OTa6+9tuPy1KlTU1u76TPoHnvskZtvvjl33XVXzjjjjI22H3rooZk/f37uvvvufP7zn0+SfOxjH8ttt92W2267Lc8991yOP/74cu8mAAAAW9DrA+wBBxyQIUOG5PDDD8+///u/55//+Z97ZL/nn39+Lr744hx++OE5++yzM3To0A22n3feeTnzzDPzrne9K0cffXSqq6vz7W9/O1OmTMmUKVPy3HPP5eabb+6RsQIAAPQHvT7A/vWvf+34fdSoUXn++ee3eJuBAwfmmmuuye23354bb7wxO++882bbX3755RsF1EmTJuXWW2/NunXrcu+99240s/vQQw+luro6gwYNyrp167Jq1aqObQcccEAeeeSRNDc3l3MXAQAAKEOvXwO7dOnStLa2ZuHChRkyZEgOOeSQLd7mhBNOyFNPPZXTTjstp59+es4555xcffXVm2x/7rnnbnTdoEGD0tbWliRpamrKLrvsssH2G264IfPmzcvq1aszd+7crF69umPbKaecssHHlQEAANh+vT7ATp06Nc3Nzfmbv/mbHHjggbnsssvyoQ99aLO3mTBhQhYsWJAkWbBgQY455pisWrUqQ4YM6WgzdOjQzc6QrlmzJlVVVWltbc2oUaPy4osvbrD90ksvzWGHHZZFixZl3rx52XffffPwww8nSf7+7/8+F1100bbe5e1SVgGJrqwxsY2FGHzROACF8err5uIk9UlmVHAsfUHn9yHeEgBbodcH2OyYvLTmpWRssmyHZRm1+6hkbDJuj3FZ/NziJMmYdWNS3VqdkUNHpmbnmqxoXJGpR0zNA3c+kOPefVxefObFjFw3Mm9+05vz9vFvz6rmVTnu6OMy/3fzM3H0xJK7fezBx3LGB87I7+/6fQ75u0My++LZG7QdMnBIRg8ancG7Ds6AlgF5W83bsm7puvzN2/4mzz71bPYcvmcyvCcO0IaaU8bHlp/pwh2O3rabTUzp496lViVZvvkmTWlKYxq7fywAAMB2690Btjr59b6/zhmHnJHb7749QwYN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6is7gBnd0GdLkisixAIAsAEBti8YnmSH5B9O+of2WdckE9dMzHvz3lz6kUszc/CGxXp2feOuuePf7kjWvXbd1bm64/dL6y/Npbl0g9s0pCFHfemojXb9+tu9al3WZdrsaRtdP7O+fRx/zV/znq++Z6Ptt6z/j9cpIxzO6JYEuRW6MD/Xp779UwMnpf15LcACAPA6/TLA9tl1dkuTPFviuk7+ado/9cRo2JIirG8tR7nFjMv4s6tLXRZncepTnxmZUfnZZQAAepWqSg8AAAAAyiHAAgAAUAgCLAAAAIUgwAIAAFAIfb+IUx+t10Qv0leKMXW3zoegzKJOnfXZImwAAGyRGVgAAAAKQYAFAACgEARYAAAACkGABQAAoBD6fBEnBV/oSnV1ijEBAEClmIEFAACgEARYAAAACkGABQAAoBD63BrY2lprXtk21rf2sFKH258vAACbYQYWAACAQhBgAQAAKAQBFgAAgEIQYAEAACiEQhdxUrCJcinQBNB/jBgxIrfcckv222+/HHzwwXnwwQczfPjw/OQnP8nQoUOzbt26nHXWWVm0aFHJ25955pkZMWJErrjiipLbFyxYkEmTJiVJhgwZkptuuilTpkwp2XbgwIH5zne+kwkTJuSPf/xjPvnJT26wfc8998zVV1+dQYMG5Wc/+1kuu+yyjm0f/OAH8/Wvfz1jxozZhqMA0DeZgQUA+pTm5ua8733vy3XXXddx3dq1a3PWWWfliCOOyJe+9KWcd955PTKW4447Ln/9619z+OGHZ/jw4Zk8efIG2y+44IL8x3/8R4488sgcccQRGTduXJJkwIABOfnkk/P000/3yDgBikKABQD6lHXr1mXp0qUbXNfS0pLFixcnSdasWZO1a9eW1denP/3p3H333bnrrrvyzne+c7NtzzzzzBx88MEbXDd58uT8+te/TpLcdNNNede73rXB9r333jt/+tOfkiR//vOfOwLuhz/84Vx33XVpbW0ta5wA/YUACwD0G4MGDcrnP//5fP3rX99i29133z3HH398DjnkkHz4wx/Ol7/85c22v/rqqzN//vwNrhs1alRefvnlJElTU1N22WWXDbYvXLgw7373uzNw4MAceeSRGTVqVKqqqnLqqafmv/7rv7by3gH0fYVZA2u9K0lSlzLWslruCsAmzJkzJ7Nnz87jjz++xbZvfOMbc//996etrS2LFi1KdXV1kqStra2jzdChQ9Pc3LzJPl566aWMHDkySXuYffHFFzfY/qUvfSmzZ8/Oxz72sTz99NN57rnncvrpp+fHP/7xBvupuO58bfUWD9gKZmABgH5h1qxZeeKJJ/LjH/+447qdd945w4YNK9n+ySefzAEHHJABAwakpqYmy5Yt67h+//33T5IceuiheeCBBza5z/nz5+eYY45JkkydOjV33XXXBtuXLl2ak08+Oe9973szePDg3H777XnrW9+aj3zkI/nlL3+ZiRMnblDYCaC/K8wMLABAWaqTG+fdmAP2OyD7vG2f1M+tz6/v+HVqa2tz14K78u5j3517/nBP/vVL/5pP/Z9P5ba7b8utv7v1tduPSrJjsqRqSX56209z1/+7K21pyyf+7RPJ2GTW12blW9/4VgYOHJhXVrySj5770WRscuapZ+aRvzyS+X947WPEP7/35/nAhz6QO+ffmfv+577MXzQ/GZvM/vLszPzszEw9cmo++/HPprW1NV/55leyYuSKnP+18ztuv+CXC/Kpr34qGdtzh6+k7pwMrvR9e72VSZoqPQhgcwRYAKDvqE7y8eQffvcPye/WX7dzkg8kO/zHDhu2nZHseuiuuePlO5L9Xrv66lzdsf3Stktz6Y2Xtl+e3P5/Qxpy1K1HvXaDU153u/+V9v/XW5d1mbZwWrLwtX0myczHZyYzkl/lV/nVLb9qv3Lf9f+/zqQbJnXcps/qTfevJckVEWKhFxNgAYC+Y3iSHZLMS7J0C22T/FP9P3XzgPqI7gyZ9d3Y99YYneSktD+HBFjotXptgFW0qX8pqzhTe0MA2LKlSZ6t9CAqr66uAC+cMze+qracyk7eKkK/1GsDLADA643JmFSnevON1iRZvP4nGbF4RKWHsE0mZmLP73RN0rSsKY1p7Pl9A2UTYAGAXm9MxuSqXJVhKV0xuMPSJHN6ZEjF0Fs+nruV5lTiQVyaNF/RnGk7TxNioRcTYAGAXq861RmWYbkoF2VRFm264egkJya5PmWtge3rZs4o8fncApid2Vtu1MXhvGZUTWYtm5Xq1moBFnoxARYAKIxFWZSGNGy6weAk49b/JMvHLa/0ELbJZh/j7uJdMRRCj/+pKs7U/xSigAQ9z6kAoGwbFTvs4y+t5RR3rK0r8ULitQX6vKpKDwAAAADKIcACAABQCAIsAAAAhdCla2Ctb+1/rG8FgK7ltbU8pdbJbrQu1ltT6HPMwAIAAFAIAiwAAACFIMACAABQCAIsAAAAhVB2Eafa2tpMHD0xUzM1866fl4alDd05LnqDjb4zXVEJelat6htAH1PytdTLa5fpfHw3KuqUKOwEBbdNVYhrhtYko7t6KJVXM7Sm0kMAAABgE7YqwDatbkrz4ObM+uus7hpPxTUPbk7T6qZKDwMAAIBOtirANr7SmGk7TUt1dXV3jafimlY3pfGVxkoPAwAAgE62+iPEja80CnhFV+ZaG2teAaB8Zb1uemkF2C6qEAMAAFAIAiwAAACFIMACAABQCAIsAAAAhbBN3wNLwZRVU0JVCbpZGV8cX/u6RvWp78bBAGwfBZuKodTjVFtX4gWpjNcooHcwAwsAAEAhCLAAAAAUggALAABAIQiwAAAAFIIiTv2Qgk10u60s2ATQm5X9uunlFaDbmYEFAACgEARYAAAACkGABQAAoBCsge1rXl1/szhJfZIZ1rzSzcpcymrNK1AUZb1uemkFqAgzsAAAABSCAAsAAEAhCLAAAAAUggALAABAISjiBGzaNtZdUrAJKAoFmwCKxQwsAAAAhSDAAgAAUAgCLAAAAIUgwAIAAFAIijgVXV2StvW/z6jkQCic2s4XFV4C+r6yijbRp5V6DngNhOIwAwsAAEAhCLAAAAAUggALAABAIVgD28e8uq5jREYkSWZmZpZneSWHRFcqc4mOtTwA28EyWYBeywwsAAAAhSDAAgAAUAgCLAAAAIUgwAIAAFAIijhBpZRRZ0kxJoBtV1dONSYFmwAKxQwsAAAAhSDAAgAAUAgCLAAAAIVgDSx0tRLLVq1lBQCA7WcGFgAAgEIQYAEAACgEARYAAIBCEGABAAAoBEWcYGso0ARQbHWVHgCV5nUbis0MLAAAAIUgwAIAAFAIAiwAAACFIMACAABQCIo4wSbU1iryAFAUdeurMy3O4tSnPjMyo8IjAqA7mIEFAACgEARYAAAACkGABQAAoBCsge1jXv1y7omZmDmZk9mZndNzeoVH1QuVWN7qi80BAKB3MwMLAABAIQiwAAAAFIIACwAAQCEIsAAAABSCIk5FV5tkbJIZSeqTzKzscHqr2loFmgD6krrUldMIgD7GDCwAAACFIMACAABQCAIsAAAAhSDAAgAAUAiKOPUDtdmwgFFZhS8KQnEmAADoP8zAAgAAUAgCLAAAAIUgwAIAAFAI1sD2NZ2XhNZnoy9y77wmdlN6cq1syTFZ3goAdDXvL6DQzMACAABQCAIsAAAAhSDAAgAAUAgCLAAAAIWgiFN/sI3FCmrryrihQggA9Aav1h1sW/9zRqUGAkB3EmD7uJrUbPuNF3fdOKBsa9L+3Fuz6Sbb9bwGAKCwBNg+qilNaU5zZmXWtndS33XjgbItTTJny82a05ymNHX7cAAA6D0E2D6qMY2ZlmmpTvW2d1LOx6+EXLra6CQnJrk+7WF2E5rSlMY09tCgAADoDQTYPqxx/X/bTDilEgYnGbf+J0CSutRlREYkSWZmZpZneYVHRFHUKtYBfY4qxAAAABSCGdi+ZHSlBwBdwPMYAIBNEGD7gpVJWpKcVOmBQBdpSfvzGgAAXkeA7QuaklyRZHilBwJdZGWiwDAAAJ0JsH1FU7zhBwAA+jRFnAAAACgEARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAEAACgEARYAAIBCEGABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEIQYAGAXq02tZmd2UmS2Zmd2tRWeEQAVIoACwAAQCEIsAAAABSCAAsAAEAhDKr0AAAAttury2LHJpmRpD7JzMoNh8rYaH205dLQ55iBBQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgEARYAAAACkGABQAAoBAEWAAAAAphUKUHAACwtWpTu8HlutRVaCQA9CQzsAAAABSCAAsAAEAhCLAAAAAUggALAABAIQxoa2trq/QgAAAAYEvMwAIAAFAIAiwAAACFIMACAABQCAIsAAAAhSDAAgAAUAgCLAAAAIUgwAIAAFAIAiwAAACFIMACAABQCP8ffxmk7u9IWlwAAAAASUVORK5CYII=",
107 | "text/plain": [
108 | ""
109 | ]
110 | },
111 | "metadata": {},
112 | "output_type": "display_data"
113 | }
114 | ],
115 | "source": [
116 | "result.plot()"
117 | ]
118 | },
119 | {
120 | "cell_type": "markdown",
121 | "metadata": {},
122 | "source": [
123 | "### now perform the calculation with strict matching only"
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "execution_count": 6,
129 | "metadata": {},
130 | "outputs": [
131 | {
132 | "data": {
133 | "text/html": [
134 | "Segmentation Metrics
Strict matching (IoU threshold: 0.5)
| Metric | |
|---|
| n_true_labels | 13 |
| n_pred_labels | 14 |
| n_true_positives | 11 |
| n_false_positives | 3 |
| n_false_negatives | 2 |
| IoU | 0.841 |
| Jaccard | 0.688 |
| pixel_identity | 0.959 |
| localization_error | 5.305 |
"
137 | ],
138 | "text/plain": [
139 | "============================\n",
140 | " Segmentation Metrics (n=1)\n",
141 | "============================\n",
142 | "Strict: True (IoU > 0.5)\n",
143 | "n_true_labels: 13\n",
144 | "n_pred_labels: 14\n",
145 | "n_true_positives: 11\n",
146 | "n_false_positives: 3\n",
147 | "n_false_negatives: 2\n",
148 | "IoU: 0.841\n",
149 | "Jaccard: 0.688\n",
150 | "pixel_identity: 0.959\n",
151 | "localization_error: 5.305"
152 | ]
153 | },
154 | "execution_count": 6,
155 | "metadata": {},
156 | "output_type": "execute_result"
157 | }
158 | ],
159 | "source": [
160 | "result = umetrix.calculate(y_true, y_pred, strict=True, iou_threshold=0.5)\n",
161 | "result"
162 | ]
163 | },
164 | {
165 | "cell_type": "code",
166 | "execution_count": 7,
167 | "metadata": {},
168 | "outputs": [
169 | {
170 | "data": {
171 | "image/png": "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gc5z+OGH53Of+1z69euXH1z5g+QnycIszIIsWK/dNddck8svvzwPPfTQBuuoqanJ5ZdfnlNOOSVJMmnSpBx44IGpqyt9vt55551z/fXXZ/DgwZkxY0auv/769ZYfcsghufzyy9Pc3Jxbb701F198cXbZZZf85rrfpKpfVR79yaO5/8r7y36My7Ks7LY9weRM3qr7OdcCUCSKOAH0MgMGDMinP/3pvO9978sRRxyRX/3kV12y3QsvvDCXXnppDjvssJxzzjkZOHDgessvuOCCnHnmmXnPe96To48+OtXV1bnooovy2//6ba474rrUHF6T7cdu3yV9BQC6JwEWoJd5z3vek8bGxvz0pz/N3LlzM2qnUZu9T9++fXPDDTfkrrvuyi233JIRI0Zssv1VV121QUCdMGFC7rjjjjQ1NeWBBx7I3nvvvd7yhx9+ONXV1enXr1+ampqycuXK7L777nn+T88nSer/XJ83HfSmLXy0AEBPIsAC9DI77bRT3vzmN+e4447LrFmzcu4Xzt3sfU444YQ89dRTOeKII/L9738/55676fucd955Wbly5Xq39evXLy0tLUmShoaG7LDDDustv/nmmzNnzpw88sgjueuuu7Jq1arMnz8/ux25W/r07ZOaI2oycPj6oRgA6F26xxzYEtOlzHntQUo9laZcQcUsXbo0v/3tb7NmzZrccccdufiii7M8yzd5nz322CPz5s1LksybNy/HHHNMVq5cmQEDBrS1GThwYBobGze6jjVr1qSqqirNzc0ZPnx4XnrppfXO9WddcVbmHjo3Sxcuzb/M+ZeM3mt0VnxpRd4x4x3Z/2P755WnX8my5zcyr7W3vWV04Dm0nPdb82QB6C6MwAL0Mv/v//2/vP3tb0+S7Lfffnn68aeTJDuN3Wmj93nssccyYcKEJK1fBV6wYEEWL16ccePGZdCg1p/fOeSQQ/KXv/xlo+t44IEHMnHixPTt2zcHHHBA/vrXv663vKW5JSsbViYtyapXV2VA9YCsWLIiN558Y773vu+lqn9VnrzryW156ABAwXWPEVgAusxLTS/lJ3f/JHffd3eam5vzn5/4z3wun8tX/ucrOXzy4Vm9evXrjQclGZ3c/Lubc+LpJ+bu++7O8hXLc/q/n56MST531edy+69vz+rVq/Pw3x7Oz//082RMclXdVbnoSxet9zXiS6+5NLO/PjsXX3pxvvndb2bVDqtStXdVdj9g9/z6u7/O3P+em5NvOznNTc1Z/PfFmffUvLz9Q2/PpI9PSktzS375jV9m4bCFybASD6ql03db9zKm0h3YQiuSNFS6EwD0BAIsQG9SneTjyTe2+0a+8YtvJEnGHzA++WPyRNMTWX3W6vWan/XIWckRSY5ITv/z6cmf1y34l9aLn+Vn+dktP3v9DlNbL85bdF5y5vqbfj7P56g7jmq9MrK17efyufXv97PzNlhXbl93ude6/3l93xTF6iRXR4gFYJsJsAC9yeAk2yWZk2TJutvWJGlOak+uTfp3bXemdlQSK1qg21Yzu3pz27DBUUlOSuuxJ8ACsI26PsD2tkIbAN3RkiTPlbitE5VVnM97RHmmbeX9trIWk0JPAHQXijgBAABQCAIsAAAAhSDAAgAAUAgCLAAAAIXQLaoQl1XYA4DCKPu87vTftcrZ3x1Y6ElhJwA6mhFYAAAACkGABQAAoBAEWAAAAAqh8+fA1rW/asITQK/k9F8MpZ4nU1kB6CaMwAIAAFAIAiwAAACFIMACAABQCAIsAAAAhdCxRZxeK/ywKMnMJFM7dO0AdFMbFOhTsKlnaf98KuoEQIUYgQUAAKAQBFgAAAAKQYAFAACgEARYAAAACqFjiziVsEFhDwB6Hqf63qXU812isFNd6rIoizIzMzM1UzMzMzu9awD0bEZgAQAAKAQBFgAAgEIQYAEAACiETp8DC0DPUldnwisllDkvFgC2hRFYAAAACkGABQAAoBAEWAAAAApBgAUAAKAQtq2IU137q603DM3QJMm0TMuyLNumTQAAxVT7hipOMzOzgj0BoKcwAgsAAEAhCLAAAAAUggALAABAIWzbHFgAerS6urrNNwIA6CJGYAEAACgEARYAAIBCEGABAAAoBAEWAACAQii/iFNdkpZ1f09N0qczugMAAAClGYEFAACgEARYAAAACkGABQAAoBAEWAAAAAqh/CJO0IlqU1vpLgBJ6urqKt0FCqq21nkcgM5nBBYAAIBCEGABAAAoBAEWAACAQjAHFgDYIuoWAFApRmABAAAoBAEWAACAQhBgAQAAKAQBFgAAgEJQxAmgt6pbd7koycwkUyvYF7q1DYo2qeEEQIUYgQUAAKAQBFgAAAAKQYAFAACgEARYAAAACkERJ4Beqm5dFaehGZokmZZpWZZllewS3cAGBZtabwSAbsEILAAAAIUgwAIAAFAIAiwAAACFYA4sna/kdKrXb5yZmV3YGQDeaIM5r+a7AtCNGYEFAACgEARYAAAACkGABQAAoBAEWAAAAApBESeA3qIuScu6v6dWsiN0hQ2KM228IQAUhhFYAAAACkGABQAAoBAEWAAAAAqhQ+fAvjbfZnzGZ1ZmZUZmZHImd+QmKILa9ldNsALoSGWdV516AeiBjMACAABQCAIsAAAAhSDAAgAAUAgCLAAAAIVQfhGn2iRjkkxNMjPJc0nqOqdTANBbKdAEABtnBBYAAIBCEGABAAAoBAEWAACAQhBgAQAAKITyizhtpfbFKOpUfupZShQSKasACQClz5dOoQCwUUZgAQAAKAQBFgAAgEIQYAEAACiEbZsD236ejumtAJAkqa01mRUAOpoRWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgELatiNNWKPWj7XWqPxVDiXokpZ5PgN5GwSYA6BpGYAEAACgEARYAAIBCEGABAAAohI6dA9t+CtDMpJzprebFdlO17a+a4wX0PiXPfU6HAFARRmABAAAoBAEWAACAQhBgAQAAKAQBFgAAgELo2CJOpbQvdFFmbab2RTMUdepkJWuUqFIC9EJOfQDQbRmBBQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKofOLOLVXqjhGGfWZShUUUtip4yjYBL3Pa6/78RmfWZmVGZmRyZlc4V51MQXsAKBQjMACAABQCAIsAAAAhSDAAgAAUAhdPwe2lA6cF7vhasyTra01nwtI67l2TJKpSWYmmVbZ7nQ150IAKD4jsAAAABSCAAsAAEAhCLAAAAAUggALAABAIXSPIk6ltK+1sZW1mHp6oacNHp8aJUC52p8vZia1devfWOjzo6JNANDjGIEFAACgEARYAAAACkGABQAAoBAEWAAAAAqh+xZxaq/cWhxbUW+knEJP3UJBugkUWPu6cHXlnXi6stiT4kwA0Ht1aoCtSU1nrr60RV2/SbbSmrQ+X2s23qQixxAAANAtdUqAbUhDGtOY6ZneGavftJldv0m20pIkszbfrDGNaUhDp3cHAADo3jolwNanPlMyJdWp7ozVb9rUrt9kl+lp4XxUkhOTzE1rmN2IhjSkPvVd1CkAAKC76rSvENev+6/LdVTI68jpXKZrldY/ydh1l0D3VOb5q9y5slu7fgCARBViAAAACqI4VYgB6FTbVDRNAT02pkTBPgX6ANhaAixAL9chhfd62hx9Os5GCvYp0AfA1hBgAXq5Dim8t7UF9ATfnm8jBfsU6ANgawiwG6OwCNCLbHPhPUGUjVGwD4AOtHUBdlQH94LeyXEEleP1R1dxrAHQgbYswK5IsjrJSZ3SF3qj1Wk9roCu4TxOJTjXA9BB+rS0tLSU1bBPn9Y/qpMM7sQe0busSNTwgC7mPE5Xc64HYDPKjKVbEWABAACgA5UbYKs6uR8AAADQIQRYAAAACkGABQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgEARYAAAACkGABQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgEARYAAAACkGABQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgEARYAAAACkGABQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgEARYAAAACkGABQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgEARYAAAACkGABQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgEARYAAAACkGABQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgEARYAAAACkGABQAAoBAEWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgEARYAAAACqFfpTsAAEDnqEtdRbdfm9qKbh/oeYzAAgC9zoQJE3LnnXfmzjvvzCOPPJIrr7xyo22vueaa7L333iWX1dTU5MYbb2y7PmnSpNTWbjy01dbW5q9//Wvb9e9///upqanZikcA0DsZgQUAep158+Zl4sSJSZJvfetbufnmmzd/nyRjU5WqN/z7f9/0y/bpk+fWfaTaLn2zXaoybSMfsYamKgNaWvLScR/Mqp/+LNXpk/emX5o66SPZkGw8mHeFs7vRR83mNGdRmjOh0h0Btkn3OasAAHSxvn375sADD8zZZ5+92bZj+/bP2O9em+yyS7J8eTJ5cpK1SVqyc9aua9WUpDlDsza56qrkoouSlSvfsJbm5KtfzYjzPpH89OYkLRmUtUnfluS7311/3cOGJd/7XvLcc8n48cn55ye/+lVywAHJV76S9OuX/PjHyRVXbKLXDVu3YzrI9hXdeilVSZor3QlgGwiwAECvdeSRR+buu+9OS0vLZtsOOuHE5Kmn0nT66Xl18pnpe+4ns/K667N9+mRpuxHYZemXnHfBunu+/nFraKqy5rn6DPj7E2k85PAMTp8sS7/0O+Hk9H/qmSw7/cwMnHx627pHjByZJYcdmb5vfnO2//J/Zemv7s6IL1+WpSeempalSzN87o155frvp7m+vmSfh2TINu+jbbE8yyu6/deMztr0TdaNnguwUGQCLADQa51yyim54YYbymrbb4/dk3nz8kL65Yh592f6Me/NBSuX5VsDtsvx60ZgPzCwf/ZsXJ7L2kZk11eb5jyQpiz4ypfzla98JStWrMiFWZvT9tgtC+b9LnOzNnuuW/fnsjZX/PWvOblpVb44ZXJO33+/fLfuc/n0ge9O4x/nJUmWDhyYn37xC3nuuefKe8DdsKZSVxR6ei793jBKDhSZAAsA9C4zZiQjd0jfqj456L1HZ+oOw5NzP54kGTtwYBat95XfJAdMSHYZk/OHbJ99d/hILjnttLx3t12zYPCQLL766xl36KEZ9KM5aWxqyiHvfFfueKE++cd/KL3tt709Ofqo/O3557LmgP3zjqHbJ9Xb57ERIzJhxA6Z++HTMmHX1nXnm1en5Z37JDf9MFcO2z6HDds+l737H3JIY2Mm//1veWXt2tbxxF13SXbdpbzHftNW77VO9MNO38L+zW/48nBPLGHakuTFl5Jp0yrdE+h0AiwA0LuM3CEZNToTR4zIr5ctS8vI0W2LZu+zT47985+z+o1fKR44MBm+Q65ZsSLfHTEiPzj66Cxvasrp8+cnI0fnc08/ndsnvjerW1ry8PLl+fmi55KRo3PVW96Six5/PCub3/CV1cFDkqbmZM3aXPb84vzugDclI0bm5lWrcuLwEbn7va+ve9iIkcmAAcnI0VleVZWmqr5ZPmBwLnjyyVy//4RUJVnd0pIP/vWv629jUwZ0zC7sWIM7fQtljk8DBdCnpZxJH0n69OnT2X0BAOh8N/0wGTk6aW5KXn6p7eaqJFfvt3/O+eMfSt5tzBtG8Z7r4lG8IUM7aC7rso5ZTUfqinmylXzuOt2IHZKqvsmLLyQnn1rp3sBWKzOWGoEFAHqpl19a7wN/c5JzNtH8D+vmUT6ffhnTxfMp/1ddXcesqJfOga3kc9fpXvsHGeglBFgAgK5SIofWlbqxC7dflk7MmOU+/q4IukD319O+RAEAAEAPJcACAABQCAIsAAAAhWAOLABAZ6j0fNeOVE63O3mKavt9Z04s9E5GYAEAACgEARYAAIBCEGABAAAoBAEWAACAQlDECQCgI9S1v1rQgk1bq9TD7cQ6S6X2r8JO0PMZgQUAAKAQBFgAAAAKQYAFAACgEMyBBQDYUiXme/a6Oa/l6OJ5sUDP1+1HYPv06ZNrr702v/71r3P33Xdn991332jba665JnvvvXfJZTU1Nbnxxhvbrk+aNCm1tRs/g+6888657bbbcs899+SMM87YYPkhhxyS+++/P/fee28+//nPJ0k+9rGP5c4778ydd96Z559/Pscff3y5DxMAAIDN6PYBdt99982AAQNy2GGH5T//8z/z7//+712y3QsvvDCXXnppDjvssJxzzjkZOHDgessvuOCCnHnmmXnPe96To48+OtXV1fnWt76ViRMnZuLEiXn++edz2223dUlfAQAAeoNuH2CfeeaZtr+HDx+eF154YbP36du3b2644YbcddddueWWWzJixIhNtr/qqqs2CKgTJkzIHXfckaampjzwwAMbjOw+/PDDqa6uTr9+/dLU1JSVK1e2Ldt3333z6KOPprGxsZyHCAAAQBm6/RzYJUuWpLm5OfPnz8+AAQNy8MEHb/Y+J5xwQp566qmcfvrpmTx5cs4999xcd911G21/3nnnbXBbv3790tLSkiRpaGjIDjvssN7ym2++OXPmzMmqVasye/bsrFq1qm3ZKaecst7XlQEAANh23T7ATpo0KY2NjXnb296W/fbbL1deeWU+9KEPbfI+e+yxR+bNm5ckmTdvXo455pisXLkyAwYMaGszcODATY6QrlmzJlVVVWlubs7w4cPz0ksvrbf8iiuuyKGHHpqFCxdmzpw52WuvvfLII48kSf7pn/4pl1xyydY+5G1SVgGJjqwxsZWFGPzQOACF8dr75mVJlicZUsG+9ATtP4f4SABsgW4fYDMkeXnNy8mYZOl2SzN8p+HJmGTszmOz6PlFSZIdm3ZMdXN1hg0clpoRNVlevzyTDp+Uv/z6LznuyOPy0rMvZVjTsLzlzW/JO8e9MysbV+a4o4/L/b+9P+NHjS+52cceeixnfPCM/O6e3+Xgdx+cGZfOWK/tgL4DMqrfqPQf2T99VvfJO2rekaYlTXnbO96W5556LrsM3iUZ3BU7aH2NKeNry8924AZHbd3dxqf0fu9QK5Ms23SThjSkPvWd3xcAAGCbde8AW538cq9f5oyDz8hd996VAf0G5PxfnJ9MTWZ/ZHaOveHYDH9xeK69+toMWjMoe63cK+NeHpcV312RvY7aK6fOOTVNy5sy//T5mfXyrKy9aG1+84PfpGV1S5Y/vDx7/GCPnJ7T85ar3pLHL3o8zSub2za9Xe12OX728an6dFUWfX1R/vvZ/87QfYZm2EHDsmjGovT/3/3zq+t/lZa1LVnx6IoM/8XwJMmbj3pzls1elllLZlVop5WhG3RtUiZVugtJWgP/lEwRYgEAoAC6d4AdnDT3b87pp5+eLHn95qqqqjz65kez+hurU72mOoPWDMolwy/JwgsWtjYYkeSTb1hP37SOFN6f5ANvuP210cNLkgxd9/9r1iY5rV3bZ5PctO7vB5McV2Jd//9217vYSTlp841O7MANzt26u83JnA7sRAnDkxyZ1v4tKd2kJjWZnumpTrUACwAABdC9A+xrliR57vWrzWnOOWees16ThUsXZkEWdG2/uqFBGbT5Rrt04AY3Eg43p9Ofq/5Jxq67BAAAeoRiBNheqK6uIystdaJyulmiOEP7YlOKOgHQbZRVD7Eg79NFUGpXbuXHAp8voOfr9r8DCwAAAIkACwAAQEEIsAAAABSCObAdrOScmN4+TaaMuS2l9pt5KwAAwBsZgQUAAKAQBFgAAAAKQYAFAACgEARYAAAACkERp41QjKmTlfMj8bUKOwHQyby3d09lFIAEeicjsAAAABSCAAsAAEAhCLAAAAAUQu+cA1vX/qoJMEXR/rkyJxaAzvbae8+QXJmkIUMypLIdAujFjMACAABQCAIsAAAAhSDAAgAAUAgCLAAAAIXQ44s41dUp0FRYfsQcAHhN+88FPhNAr2QEFgAAgEIQYAEAACgEARYAAIBCEGABAAAohGIXcapLsijJzCRTk4ytbHfoenUlKj3VquoAwMbUJRm67u+hm2oIQHdkBBYAAIBCEGABAAAoBAEWAACAQij2HNgSSs2JpAfxI+YAQLLhZ4LE5wLoBYzAAgAAUAgCLAAAAIUgwAIAAFAIAiwAAACFUJwiTmozAQCwCbWqOEGPZwQWAACAQhBgAQAAKAQBFgAAgEIQYAEAACiE4hRxKqEudRmaoUmSaZmWZVlW4R4BAFAx7Yt+qukEPY4RWAAAAApBgAUAAKAQBFgAAAAKofvOga1L0rLu76mV7AgAAN1NbTkTXF+bE3tZkuVJhqy7BArLCCwAAACFIMACAABQCAIsAAAAhSDAAgAAUAjdt4gTbKW61GVRFmVmZmZqpmZsxpZX6AEA6LY67L28bvNNfGyA7ssILAAAAIUgwAIAAFAIAiwAAACFYA4sAAC8Ual5subFQrdgBBYAAIBCEGABAAAoBAEWAACAQhBgAQAAKARFnCg2RRYAoMep7Y5v5qU+c7TXDbsNPY0RWAAAAApBgAUAAKAQBFgAAAAKQYAFAACgEBRxAgCALVRXVlWn8nTLolXQTQmwAABQhnkzk7GvVKWqpSpDcmWHrffsTXwkb05zFqU5Ezpsa1BsAiwAAJRh7CtVGbusOUlzkoYOW+/2m21RtW6bgAALAABlqGppDZJNSVYMqd6wwfKtW+/yjdxxdNamb5IqARbaCLAAAFRMUeZ/1qVu3deGG7JiSHWu+l/nl3fHrXx4tanNc+mXnbN261YAPZQqxAAAABSCAAsAAEAhCLAAAAAUggALAABAISjiRK/Q/sfGi1IwAgAouLp2130EgW1iBBYAAIBCEGABAAAoBAEWAACAQhBgAQAAKITuG2Brk8xc9/fMTTUEAACgN+i+ARYAAADeQIAFAACgEARYAAAACqFfpTuwLWpTm/EZn1mZlRmZkQVZkLoNfi0aAGCd2iQ3JRmQZFm5d6lNkpydftk+yfIs76TO0Z3Vpna9Y+C14+KNyvocWqJJbe2G6wJKMwILAABAIQiwAAAAFIIACwAAQCEIsAAAABRCoYs4AQBAd1GqsBPQsQRYAADYAqOXr81zl3X+x+jRWdvp24CiEWABAKAMzX2akyR9k+y8vOvCZXOau2xb0N0JsAAAUIZFw5qTVKWqpYPLyGzip4Wb05xFAiy0KU6ALTWloNQPQbdrWNYPSgMA0CWKPE90wtQkaV73fwcq7i6BLqcKMQAAAIUgwAIAAFAIAiwAAACFIMACAABQCMUp4lTKGye8z1x3Wde+yYaz4hV2AgCSlF0kEjpVqWNOYScoyQgsAAAAhSDAAgAAUAgCLAAAAIUgwAIAAFAIxS7iVEr7Ce8lJsW3L+ykqBMAQMcrVUwTYFsYgQUAAKAQBFgAAAAKQYAFAACgEHreHNj2yph6UVtX3vwMc2W7oTKn1piDA0BHKvW+4nMCQOczAgsAAEAhCLAAAAAUggALAABAIQiwAAAAFELPL+JUjlL1fUrUYWhfsEGxBgAAOkX7j5nqUUISI7AAAAAUhAALAABAIQiwAAAAFII5sBtTxjyD2rryJiOYK9uBynle3tBoZmZ2YmcA6JHav9d4Gy9L+1ohvVFnfuazf6GVEVgAAAAKwQgsAAAVN29mMvaVqlS1dPz4yujla9sun7us8z7+DsmVnbbuszfysX3/5uS5JGOakz9s4qN9c5qzKM2Z0En9g64iwAIAUHFjX6nK2GXNSZo7bRt9k+y8Lsx2joZOW/P2G7m96g2XO2dzj60qnbl/oSsIsAAAVFzryGtzmpK8MKRjP6KOXr42fZNOWfcbDcmQTlv38uXLS97e/IbL5zfy0X50Wh9/lQBLDyDAbosy59KXU+xJoaeto6ABAN1F+/ck7+1b54Uh/TLmf3XsKOlzl/XLzsvXdui6u/z53chHnleqhrRdjtnICOxz6VfG6CwUgyJOAAAAFIIACwAAQCEIsAAAABSCAAsAAEAhKOLUFdpPui8x57+cYkS9rhiE+kzQqXrbOUXRN7paqWOuJ73uettrquLPXanN966nAJIIsADZMTumOtWV7kaXG5qhle5Clxqf8RXZbkMaUp/6imwbAHoaARbo1XbMjrk212ZQBlW6K3SyWZlVke02pjFTMkWIBYAOIMACvVp1qjMog3JJLsnCLKx0d7rUtEyrdBe61IzM6PJt1qQm0zM91akWYAGgAwiwlVDOfIUy58lWfD5GRymxT3rb3Boqa2EWZkEWVLobZemo1/2yLOuQ9RTF5Ewuq51zDxtof0gs35ZVFfO93OuiGEodS547ehpViAEAACgEARYAAIBCEGABAAAoBAEWAACAQlDEqbsqc779BhPzS9SBqHhxiDIeiwID9HQVfx1StvbPlfMTna39MdYdzhc9+bjvDvsX2HpGYIFCqKqqyuzZs3PnnXfmmmuuSb9+G//3t2uuuSZ77713yWU1NTW58cYb264fOunQ7Fa720bXtfPOO+e2227LPffckzPOOGOD5VdffXXuvPPO3HnnnVmxYkVGjBiRJPnkJz+Z22+/PXfffXfGjRtX5qMEAGBTBFigEE488cQ8/vjjmThxYh5++OGceOKJXbLdCy+8MJdeemkOO+ywnHPOORk4cOB6yz/+8Y9n4sSJOeOMM3Lffffl5Zdfzv77759dd901Rx11VA4//PA8/fTTXdJXAICeToAFCmH33XfPn/70pyTJH/7whxx66KGbvU/fvn1zww035K677sott9zSNjq6MVddddUGAXXChAm544470tTUlAceeGCjI7snn3xybrrppiTJBz7wgQwcODC/+tWv8rWvfS1VVU61AAAdwacqoBDmz5+fI488Mkly1FFHZfjw4Zu9zwknnJCnnnoqRxxxRL7//e/n3HPP3WT78847LytXrlzvtn79+qWlpSVJ0tDQkB122KHkfU888cTMnTs3SbLTTjtl7dq1ee9735sVK1bklFNO2WxfAQDYPEWcepoSNRd6ciEGeo+f/exnmThxYu6444789a9/zfPPP7/Z++yxxx6ZN29ekmTevHk55phjsnLlygwYMKCtzYCBA9LU2LTRdaxZsyZVVVVpbm7O8OHD89JLL23Q5spdrsy4tePyb4v/LUnyjqXvyNP3Pp261OVNd7wpBx18UO7KXVv4iLdAT69HUuFTWKmCL86rlDwEOui16Pjaehsr0DQkVyZpyJAM6doOAR2uGAF21CaWrUmyJKkZXlOUR0NXGJJkUVqPj42oSU1X9YYO0DKsJed/5fwkSe2na3P7b29PxiRjdx6bRc8vWr/xoCSjk8defCwTJk7I3PvmZsLRE7Lg+QVZXLU443Yfl0G7D0pjY2MOOPqALL9leet5pv+G231g/gOZePLE3HXvXTngwAPymSs+k4xZv80uH90l9912XxaNae3Hg/MfzLhDx2XRvEV55+HvzBP1T7Qt6xQtnbfqbmHM5ptsqcErBmd4w/COXzG9wuiszXOlPnRc1vV96UlGL1/bdvncZVv3oa41qJa4ffkrW90voHvp3pFvRZLVSU7aeJOGpQ1pvLox05dO76peUQRLkjy2+WaNaUxDGjq9O2yj6mSnz+6UH3zoB1nbvDa3P3577ll2T7JfMvsjs3PsDcdmddPq19vvmeSU5OYlN+fEw0/M3cfdneWrl+f0uacnU5PP/flzuf2u27O6aXWeffLZvPTvLyVnJ1eddVUu+tVFWbn29a8RX9pwaWZ/aXYu7n9xvvnAN7Nqyqrss9M+OWjcQZnxwIwkyZgpY3LKjadk8dTFSZKqPlWZceSMnHbyaXlh+Qv52NyPZc3UTfxrCps2teNX2X91//z71f8uxLJFmtOcJOmbZOes3bDB8q7tT0/VN8nOy0vs37Js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",
172 | "text/plain": [
173 | ""
174 | ]
175 | },
176 | "metadata": {},
177 | "output_type": "display_data"
178 | }
179 | ],
180 | "source": [
181 | "result.plot()"
182 | ]
183 | },
184 | {
185 | "cell_type": "code",
186 | "execution_count": null,
187 | "metadata": {},
188 | "outputs": [],
189 | "source": []
190 | }
191 | ],
192 | "metadata": {
193 | "kernelspec": {
194 | "display_name": "Python [conda env:btrack]",
195 | "language": "python",
196 | "name": "conda-env-btrack-py"
197 | },
198 | "language_info": {
199 | "codemirror_mode": {
200 | "name": "ipython",
201 | "version": 3
202 | },
203 | "file_extension": ".py",
204 | "mimetype": "text/x-python",
205 | "name": "python",
206 | "nbconvert_exporter": "python",
207 | "pygments_lexer": "ipython3",
208 | "version": "3.10.9"
209 | }
210 | },
211 | "nbformat": 4,
212 | "nbformat_minor": 4
213 | }
214 |
--------------------------------------------------------------------------------