Skip to content

Commit 794bf68

Browse files
committed
fix: docs typos
1 parent b6419fb commit 794bf68

File tree

12 files changed

+188
-55
lines changed

12 files changed

+188
-55
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,4 @@ docs/_build/
7373

7474
test_data/
7575
notebooks
76+
data

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mikan-rs"
3-
version = "0.1.2"
3+
version = "0.1.3"
44
edition = "2021"
55
license = "MIT OR Apache-2.0"
66
description = "A medical image kit for segmentation metrics evaluation, native Rust support, and Python bindings for cross-language performance."

README.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# mikan-rs
1+
# mikan-rs 🍊
22

33
A **m**edical **i**mage **k**it for segment**a**tion metrics evaluatio**n**, native Rust support, and Python bindings for cross-language performance.
44

55
## 🎨 Features
66

7-
- 🚀 **Blazingly Fast**: Written in Rust with high parallelization; speeds are 10-200x faster than medpy (depends on the number of cores in your CPU), especially for Hausdorff distance calculations.
7+
- 🚀 **Blazingly Fast**: Written in Rust with high parallelization; speeds are 10-100x faster than medpy (depends on the number of cores in your CPU), especially for Hausdorff distance calculations.
88

9-
- 🎯 **Simple**: The API is so intuitive that you can start using it immediately while reading the [documentation](examples/tutorial.ipynb) in just one minute!
9+
- 🎯 **Simple**: The API is so intuitive that you can start using it immediately while reading the [documentation](https://github.com/Plasma-Blue/mikan-rs/blob/master/examples/tutorial.ipynb) in just one minute!
1010

1111
- 🧮 **Comprehensive Metrics**: Easily to compute almost all of segmentation metrics:
1212

@@ -49,11 +49,22 @@ e = mikan.Evaluator(gt, pred)
4949
e.labels(1).metrics("dice")
5050
```
5151

52-
For details, please refer to the [python examples](examples/tutorial.ipynb) and [rust examples](examples/tutorial.rs).
52+
For details, please refer to the [python examples](https://github.com/Plasma-Blue/mikan-rs/blob/master/examples/tutorial.ipynb) and [rust examples](https://github.com/Plasma-Blue/mikan-rs/blob/master/examples/tutorial.rs).
53+
54+
## 🎄 Related Projects
55+
56+
- [medpy](https://github.com/loli/medpy): A well-known package for calculating segmentation metrics, with excellent documentation and implementation.
57+
- [miseval](https://github.com/frankkramer-lab/miseval): A framework capable of calculating a large number of segmentation metrics.
58+
- [seg_metrics](https://github.com/Jingnan-Jia/segmentation_metrics): A package for segmentation metrics that supports batch data calculation and CSV output, making it very convenient.
59+
- [MetricsReloaded](https://github.com/Project-MONAI/MetricsReloaded): A new recommendation framework for biomedical image analysis validation, published in Nature Methods.
60+
61+
## 📃 Citation
62+
63+
If you use this software, we would appreciate it if you could include an mikan emoji 🍊 in your paper.
5364

5465
## 🍚 Q&A
5566

56-
Q: Why are my results different from seg_metrics/miseval/Metrics Reloaded?
67+
Q: Why are my results different from seg_metrics/miseval/MetricsReloaded?
5768

5869
A: They are wrong. Of course, we might be wrong too. PRs to fix issues are welcome!
5970

-1.11 MB
Binary file not shown.
-4.81 MB
Binary file not shown.

examples/benchmark.ipynb

Lines changed: 159 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,66 +2,174 @@
22
"cells": [
33
{
44
"cell_type": "markdown",
5-
"metadata": {},
5+
"metadata": {
6+
"id": "8ma4uIoIZjC1"
7+
},
8+
"source": [
9+
"# benchmark: medpy vs. mikan-rs 🍊"
10+
]
11+
},
12+
{
13+
"cell_type": "markdown",
14+
"metadata": {
15+
"id": "L5D9-i91eYUY"
16+
},
617
"source": [
7-
"## Benchmark"
18+
"Please note that **Colab only provides dual-core CPUs**, so the speedup is limited. You can test on a server with more CPUs to observe mikan's blazingly fast performance."
819
]
920
},
1021
{
1122
"cell_type": "code",
1223
"execution_count": 1,
13-
"metadata": {},
24+
"metadata": {
25+
"colab": {
26+
"base_uri": "https://localhost:8080/"
27+
},
28+
"id": "y_qn133LaML8",
29+
"outputId": "618ac8ca-5e1f-4519-ee9f-343ca1a64ccc"
30+
},
31+
"outputs": [
32+
{
33+
"name": "stdout",
34+
"output_type": "stream",
35+
"text": [
36+
"Requirement already satisfied: SimpleITK in /usr/local/lib/python3.11/dist-packages (2.4.1)\n",
37+
"Requirement already satisfied: medpy in /usr/local/lib/python3.11/dist-packages (0.5.2)\n",
38+
"Requirement already satisfied: mikan-rs in /usr/local/lib/python3.11/dist-packages (0.1.2)\n",
39+
"Requirement already satisfied: scipy>=1.10 in /usr/local/lib/python3.11/dist-packages (from medpy) (1.13.1)\n",
40+
"Requirement already satisfied: numpy>=1.24 in /usr/local/lib/python3.11/dist-packages (from medpy) (1.26.4)\n"
41+
]
42+
}
43+
],
44+
"source": [
45+
"!pip install SimpleITK medpy mikan-rs"
46+
]
47+
},
48+
{
49+
"cell_type": "code",
50+
"execution_count": 2,
51+
"metadata": {
52+
"colab": {
53+
"base_uri": "https://localhost:8080/",
54+
"height": 181
55+
},
56+
"id": "a_RYW5sPX6mY",
57+
"outputId": "2a3fec85-5b1c-4b4b-82d7-d4cb961d7354"
58+
},
59+
"outputs": [
60+
{
61+
"name": "stderr",
62+
"output_type": "stream",
63+
"text": [
64+
"Downloading...\n",
65+
"From: https://drive.google.com/uc?id=1R6rph1_Wc2HfLhzvGkcNt7hgbQiHWZBY\n",
66+
"To: /content/patients_26_ground_truth.nii.gz\n",
67+
"100%|██████████| 1.17M/1.17M [00:00<00:00, 70.3MB/s]\n",
68+
"Downloading...\n",
69+
"From: https://drive.google.com/uc?id=1cShgX96WgK_j4EbfR4wN2RLgcyVR4ca0\n",
70+
"To: /content/patients_26_segmentation.nii.gz\n",
71+
"100%|██████████| 5.05M/5.05M [00:00<00:00, 28.3MB/s]\n"
72+
]
73+
},
74+
{
75+
"data": {
76+
"application/vnd.google.colaboratory.intrinsic+json": {
77+
"type": "string"
78+
},
79+
"text/plain": [
80+
"'patients_26_segmentation.nii.gz'"
81+
]
82+
},
83+
"execution_count": 2,
84+
"metadata": {},
85+
"output_type": "execute_result"
86+
}
87+
],
88+
"source": [
89+
"import gdown\n",
90+
"\n",
91+
"# We use datasets from seg_metrics\n",
92+
"\n",
93+
"gdth_url_id = \"1R6rph1_Wc2HfLhzvGkcNt7hgbQiHWZBY\"\n",
94+
"pred_url_id = \"1cShgX96WgK_j4EbfR4wN2RLgcyVR4ca0\"\n",
95+
"gdth_fpath = \"patients_26_ground_truth.nii.gz\"\n",
96+
"pred_fpath = \"patients_26_segmentation.nii.gz\"\n",
97+
"\n",
98+
"gdown.download(id=gdth_url_id, output=gdth_fpath, quiet=False)\n",
99+
"gdown.download(id=pred_url_id, output=pred_fpath, quiet=False)"
100+
]
101+
},
102+
{
103+
"cell_type": "code",
104+
"execution_count": 3,
105+
"metadata": {
106+
"id": "cxVnoqqEYd6F"
107+
},
14108
"outputs": [],
15109
"source": [
110+
"import time\n",
16111
"import mikan\n",
17112
"import numpy as np\n",
18113
"import SimpleITK as sitk\n",
19-
"import time\n",
20114
"from medpy.metric import dc, hd, hd95, assd"
21115
]
22116
},
23117
{
24118
"cell_type": "markdown",
25-
"metadata": {},
119+
"metadata": {
120+
"id": "Lmzfs9DaZyaD"
121+
},
26122
"source": [
27-
"## Load Data"
123+
"## Load datas"
28124
]
29125
},
30126
{
31127
"cell_type": "code",
32-
"execution_count": null,
33-
"metadata": {},
128+
"execution_count": 4,
129+
"metadata": {
130+
"id": "E3lZFPFNYiSK"
131+
},
34132
"outputs": [],
35133
"source": [
36-
"gt = sitk.ReadImage(rf\"..\\data\\patients_26_ground_truth.nii.gz\", sitk.sitkUInt8)\n",
37-
"pred = sitk.ReadImage(rf\"..\\data\\patients_26_segmentation.nii.gz\", sitk.sitkUInt8)\n",
134+
"gt = sitk.ReadImage(\"patients_26_ground_truth.nii.gz\", sitk.sitkUInt8)\n",
135+
"pred = sitk.ReadImage(\"patients_26_segmentation.nii.gz\", sitk.sitkUInt8)\n",
38136
"\n",
39137
"gt_arr = sitk.GetArrayFromImage(gt)\n",
40138
"pred_arr = sitk.GetArrayFromImage(pred)\n",
41139
"\n",
42140
"# Downsample for faster\n",
43-
"# If you're patient, you can comment out here and wait for the medpy to run for 30 minutes 😆\n",
141+
"# If you're patient, you can comment out here and wait for medpy to run for 30 minutes 😆\n",
44142
"gt_arr = np.array(gt_arr[::2, ::2, ::2])\n",
45-
"pred_arr = np.array(pred_arr[::2, ::2, ::2])"
143+
"pred_arr = np.array(pred_arr[::2, ::2, ::2])"
46144
]
47145
},
48146
{
49147
"cell_type": "markdown",
50-
"metadata": {},
148+
"metadata": {
149+
"id": "m9vGRSY8Z2v9"
150+
},
51151
"source": [
52-
"### DSC"
152+
"## Dice"
53153
]
54154
},
55155
{
56156
"cell_type": "code",
57-
"execution_count": 3,
58-
"metadata": {},
157+
"execution_count": 8,
158+
"metadata": {
159+
"colab": {
160+
"base_uri": "https://localhost:8080/"
161+
},
162+
"id": "nMxlyYl3YpDO",
163+
"outputId": "c87b5310-88ba-4381-8115-13a7187c3af6"
164+
},
59165
"outputs": [
60166
{
61167
"name": "stdout",
62168
"output_type": "stream",
63169
"text": [
64-
"DSC: 15.09x faster\n"
170+
"Mikan cost 0.12 s.\n",
171+
"medpy costs 0.19 s.\n",
172+
"DSC: 1.54x faster\n"
65173
]
66174
}
67175
],
@@ -71,35 +179,44 @@
71179
"evaluator = mikan.ArrayEvaluator(gt_arr, pred_arr, spacing=gt.GetSpacing())\n",
72180
"dsc = evaluator.labels([1,2,3,4,5]).metrics(\"dsc\")\n",
73181
"mikan_costs = time.time() - t\n",
182+
"print(f\"Mikan cost {mikan_costs:.2f} s.\")\n",
74183
"\n",
75184
"# medpy: DSC\n",
76185
"t = time.time()\n",
77186
"for i in (1,2,3,4,5):\n",
78187
" dsc = dc(pred_arr == i, gt_arr == i)\n",
79188
"medpy_costs = time.time() - t\n",
80-
"\n",
189+
"print(f\"medpy costs {time.time() - t:.2f} s.\")\n",
81190
"print(f\"DSC: {medpy_costs / mikan_costs :.2f}x faster\")\n"
82191
]
83192
},
84193
{
85194
"cell_type": "markdown",
86-
"metadata": {},
195+
"metadata": {
196+
"id": "YX0b4t2XZ4z8"
197+
},
87198
"source": [
88-
"### HD"
199+
"## HD"
89200
]
90201
},
91202
{
92203
"cell_type": "code",
93-
"execution_count": 4,
94-
"metadata": {},
204+
"execution_count": 9,
205+
"metadata": {
206+
"colab": {
207+
"base_uri": "https://localhost:8080/"
208+
},
209+
"id": "hrU3grdDdrCn",
210+
"outputId": "bc289aa3-2001-4455-b7b6-2f6242640b7e"
211+
},
95212
"outputs": [
96213
{
97214
"name": "stdout",
98215
"output_type": "stream",
99216
"text": [
100-
"Mikan has calculated Hausdorff distance and cost 0.78 s.\n",
217+
"Mikan has calculated Hausdorff distance and cost 4.47 s.\n",
101218
"Let's waiting for medpy, be patient for a while...\n",
102-
"HD: 68.78x faster\n"
219+
"HD: 11.14x faster\n"
103220
]
104221
}
105222
],
@@ -123,25 +240,33 @@
123240
},
124241
{
125242
"cell_type": "markdown",
126-
"metadata": {},
243+
"metadata": {
244+
"id": "vC0KgPIlZ6LU"
245+
},
127246
"source": [
128-
"### HD/HD95/ASSD"
247+
"## All Distances"
129248
]
130249
},
131250
{
132251
"cell_type": "code",
133-
"execution_count": 5,
134-
"metadata": {},
252+
"execution_count": 10,
253+
"metadata": {
254+
"colab": {
255+
"base_uri": "https://localhost:8080/"
256+
},
257+
"id": "3weKKOcMZeLC",
258+
"outputId": "4c87051f-9d4c-4e79-a192-ae8a26ccb68a"
259+
},
135260
"outputs": [
136261
{
137262
"name": "stdout",
138263
"output_type": "stream",
139264
"text": [
140265
"{'1': {'hd': 3.8066790103912354, 'hd95': 0.7410011291503906, 'assd': 0.24823972582817078}, '2': {'hd': 5.875893592834473, 'hd95': 0.8939142823219299, 'assd': 0.30189621448516846}, '3': {'hd': 7.1895952224731445, 'hd95': 0.7410049438476562, 'assd': 0.29092279076576233}, '4': {'hd': 55.0378303527832, 'hd95': 0.7410011291503906, 'assd': 0.2536499500274658}, '5': {'hd': 46.238975524902344, 'hd95': 0.7410125732421875, 'assd': 0.27448806166648865}}\n",
141-
"Mikan has calculated distance and cost 0.85 s.\n",
266+
"Mikan has calculated distance and cost 3.80 s.\n",
142267
"Let's waiting for medpy, be patient for a while...\n",
143268
"{1: {'hd': 3.8066796490554484, 'hd95': 0.7409999966621399, 'assd': 0.24827345569665876}, 2: {'hd': 5.875891921349948, 'hd95': 0.893913303991663, 'assd': 0.3018870383121832}, 3: {'hd': 7.18959419428273, 'hd95': 0.7409999966621399, 'assd': 0.2909637348388582}, 4: {'hd': 55.03783156368531, 'hd95': 0.7409999966621399, 'assd': 0.25367831066385055}, 5: {'hd': 46.23897571237574, 'hd95': 0.7409999966621399, 'assd': 0.2745253765803193}}\n",
144-
"Distances: 190.71x faster\n"
269+
"Distances: 39.67x faster\n"
145270
]
146271
}
147272
],
@@ -174,24 +299,18 @@
174299
}
175300
],
176301
"metadata": {
302+
"colab": {
303+
"provenance": []
304+
},
177305
"kernelspec": {
178306
"display_name": "Python 3",
179-
"language": "python",
180307
"name": "python3"
181308
},
182309
"language_info": {
183-
"codemirror_mode": {
184-
"name": "ipython",
185-
"version": 3
186-
},
187-
"file_extension": ".py",
188-
"mimetype": "text/x-python",
189310
"name": "python",
190-
"nbconvert_exporter": "python",
191-
"pygments_lexer": "ipython3",
192311
"version": "3.12.3"
193312
}
194313
},
195314
"nbformat": 4,
196-
"nbformat_minor": 2
315+
"nbformat_minor": 0
197316
}

examples/tutorial.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"\n",
1313
"Main features of mikan:\n",
1414
"\n",
15-
"- Rust-driven, highly parallelized, and extremely fast, 10 to 50 times faster than existing tools (such as medpy)\n",
15+
"- Rust-driven, highly parallelized, and extremely fast, 10 to 100 times faster than existing tools (such as medpy)\n",
1616
"- Supports the calculation of almost all segmentation metrics\n",
1717
"- Carefully designed simple, flexible, and intuitive interface, you can master mikan and fall in love with it in just one minute!\n"
1818
]

examples/tutorial_zh.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"mikan 是一个医学图像分割指标计算工具。此文档介绍了 mikan 的使用方法,简单对比了其与 medpy 的性能和结果。\n",
1212
"\n",
1313
"mikan 的主要特点:\n",
14-
"- rust 驱动,高度并行化,非常快,比现有工具 (medpy 等) 快 10 ~ 50x\n",
14+
"- rust 驱动,高度并行化,非常快,比现有工具 (medpy 等) 快 10 ~ 100x\n",
1515
"- 几乎支持全部的分割指标的计算\n",
1616
"- 精心设计的简单、灵活、符合直觉的接口,你一分钟就可以精通 mikan 并喜欢上它!"
1717
]

0 commit comments

Comments
 (0)