Skip to content

Commit

Permalink
Merge pull request #56 from BrainLesion/config
Browse files Browse the repository at this point in the history
updated to config branch, addded config example notebook
  • Loading branch information
neuronflow authored Aug 6, 2024
2 parents 2cd7bbb + 63089e7 commit 98e3fcf
Show file tree
Hide file tree
Showing 4 changed files with 583 additions and 53 deletions.
397 changes: 397 additions & 0 deletions panoptica/example_config.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,397 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Use Case: Matched Instances Input\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install Dependencies"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: panoptica in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from -r requirements.txt (line 1)) (0.6.6.post13.dev0+a2f5dd3)\n",
"Requirement already satisfied: auxiliary in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from -r requirements.txt (line 2)) (0.0.42)\n",
"Requirement already satisfied: rich in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from -r requirements.txt (line 3)) (13.6.0)\n",
"Requirement already satisfied: numpy in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from -r requirements.txt (line 4)) (1.25.2)\n",
"Requirement already satisfied: connected-components-3d<4.0.0,>=3.12.3 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from panoptica->-r requirements.txt (line 1)) (3.12.3)\n",
"Requirement already satisfied: ruamel.yaml<0.19.0,>=0.18.6 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from panoptica->-r requirements.txt (line 1)) (0.18.6)\n",
"Requirement already satisfied: scikit-image<0.23.0,>=0.22.0 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from panoptica->-r requirements.txt (line 1)) (0.22.0)\n",
"Requirement already satisfied: scipy<2.0.0,>=1.7.0 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from panoptica->-r requirements.txt (line 1)) (1.11.2)\n",
"Requirement already satisfied: nibabel>=3.0 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from auxiliary->-r requirements.txt (line 2)) (5.1.0)\n",
"Requirement already satisfied: path>=16.10.0 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from auxiliary->-r requirements.txt (line 2)) (17.0.0)\n",
"Requirement already satisfied: pathlib>=1.0 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from auxiliary->-r requirements.txt (line 2)) (1.0.1)\n",
"Requirement already satisfied: pillow>=10.0.0 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from auxiliary->-r requirements.txt (line 2)) (10.0.0)\n",
"Requirement already satisfied: tifffile>=2023.8.25 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from auxiliary->-r requirements.txt (line 2)) (2023.8.30)\n",
"Requirement already satisfied: markdown-it-py>=2.2.0 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from rich->-r requirements.txt (line 3)) (3.0.0)\n",
"Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from rich->-r requirements.txt (line 3)) (2.17.2)\n",
"Requirement already satisfied: mdurl~=0.1 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from markdown-it-py>=2.2.0->rich->-r requirements.txt (line 3)) (0.1.2)\n",
"Requirement already satisfied: packaging>=17 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from nibabel>=3.0->auxiliary->-r requirements.txt (line 2)) (23.1)\n",
"Requirement already satisfied: ruamel.yaml.clib>=0.2.7 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from ruamel.yaml<0.19.0,>=0.18.6->panoptica->-r requirements.txt (line 1)) (0.2.8)\n",
"Requirement already satisfied: networkx>=2.8 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from scikit-image<0.23.0,>=0.22.0->panoptica->-r requirements.txt (line 1)) (3.1)\n",
"Requirement already satisfied: imageio>=2.27 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from scikit-image<0.23.0,>=0.22.0->panoptica->-r requirements.txt (line 1)) (2.31.3)\n",
"Requirement already satisfied: lazy_loader>=0.3 in /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages (from scikit-image<0.23.0,>=0.22.0->panoptica->-r requirements.txt (line 1)) (0.3)\n"
]
}
],
"source": [
"!pip install -r requirements.txt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup Imports"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from auxiliary.nifti.io import read_nifti\n",
"from rich import print as pprint\n",
"from panoptica import InputType, Panoptica_Evaluator\n",
"from panoptica.metrics import Metric"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load Data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To demonstrate we use a reference and predicition of spine a segmentation with matched instances.\n",
"\n",
"\n",
"![matched_figure](figures/matched_instance.png)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(array([ 0, 2, 3, 4, 5, 6, 7, 8, 26, 102, 103, 104, 105,\n",
" 106, 107, 108, 202, 203, 204, 205, 206, 207, 208], dtype=uint8),\n",
" array([ 0, 2, 3, 4, 5, 6, 7, 8, 26, 102, 103, 104, 105,\n",
" 106, 107, 108, 202, 203, 204, 205, 206, 207, 208], dtype=uint8))"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ref_masks = read_nifti(\"./spine_seg/matched_instance/ref.nii.gz\")\n",
"pred_masks = read_nifti(\"./spine_seg/matched_instance/pred.nii.gz\")\n",
"\n",
"# labels are matching\n",
"np.unique(ref_masks), np.unique(pred_masks)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Build Evaluator object"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #00ff00; text-decoration-color: #00ff00\">────────────────────────────────────────── </span>Thank you for using <span style=\"font-weight: bold\">panoptica</span><span style=\"color: #00ff00; text-decoration-color: #00ff00\"> ──────────────────────────────────────────</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[92m────────────────────────────────────────── \u001b[0mThank you for using \u001b[1mpanoptica\u001b[0m\u001b[92m ──────────────────────────────────────────\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"> Please support our development by citing \n",
"</pre>\n"
],
"text/plain": [
" Please support our development by citing \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"> <span style=\"color: #0000ff; text-decoration-color: #0000ff; text-decoration: underline\">https://github.com/BrainLesion/panoptica#citation</span> -- Thank you! \n",
"</pre>\n"
],
"text/plain": [
" \u001b[4;94mhttps://github.com/BrainLesion/panoptica#citation\u001b[0m -- Thank you! \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #00ff00; text-decoration-color: #00ff00\">───────────────────────────────────────────────────────────────────────────────────────────────────────────────────</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[92m───────────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
"</pre>\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Panoptic: Start Evaluation\n",
"-- Got MatchedInstancePair, will evaluate instances\n"
]
}
],
"source": [
"evaluator = Panoptica_Evaluator(\n",
" expected_input=InputType.MATCHED_INSTANCE,\n",
" decision_metric=Metric.IOU,\n",
" decision_threshold=0.5,\n",
")\n",
"\n",
"result, debug_data = evaluator.evaluate(pred_masks, ref_masks)[\"ungrouped\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Inspect Results\n",
"The results object allows access to individual metrics and provides helper methods for further processing"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"+++ MATCHING +++\n",
"Number of instances in reference (num_ref_instances): 22\n",
"Number of instances in prediction (num_pred_instances): 22\n",
"True Positives (tp): 22\n",
"False Positives (fp): 0\n",
"False Negatives (fn): 0\n",
"Recognition Quality / F1-Score (rq): 1.0\n",
"\n",
"+++ GLOBAL +++\n",
"Global Binary Dice (global_bin_dsc): 0.9744370224078394\n",
"Global Binary Centerline Dice (global_bin_cldsc): 0.9637064011802574\n",
"Global Binary Average Symmetric Surface Distance (global_bin_assd): 0.1499152780072207\n",
"Global Binary Relative Volume Difference (global_bin_rvd): -0.0006011763989268869\n",
"\n",
"+++ INSTANCE +++\n",
"Segmentation Quality IoU (sq): 0.8328184295330796 +- 0.15186064004517466\n",
"Panoptic Quality IoU (pq): 0.8328184295330796\n",
"Segmentation Quality Dsc (sq_dsc): 0.900292616009954 +- 0.10253566174957332\n",
"Panoptic Quality Dsc (pq_dsc): 0.900292616009954\n",
"Segmentation Quality Assd (sq_assd): 0.250331887879225 +- 0.07696680402317076\n",
"Segmentation Quality Relative Volume Difference (sq_rvd): 0.0028133049062930553 +- 0.034518928495505724\n",
"\n"
]
}
],
"source": [
"# print all results\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Save Evaluator as config\n",
"\n",
"You can save your settings and arguments for nearly all panoptica-related objects as yaml configs"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Saved config into /opt/anaconda3/envs/seg11panoptdev/lib/python3.11/site-packages/panoptica/test_config.yaml\n"
]
}
],
"source": [
"evaluator.save_to_config_by_name(\"test_config\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load Configs\n",
"\n",
"You can simply load the same object by using its class.load_config:\n",
"\n",
"Notably: \n",
"\n",
"- load_from_config() uses an absolute path, while\n",
"- load_from_config_by_name() uses some default path\n",
"\n",
"The same is true for saving configs:\n",
"\n",
"- save_to_config() saves to a given absolute path, while\n",
"- save_to_config_by_name() uses a default path"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<panoptica.panoptica_evaluator.Panoptica_Evaluator object at 0x7fbe999a9c90>\n"
]
}
],
"source": [
"eval = Panoptica_Evaluator.load_from_config_name(\"test_config\")\n",
"print(eval)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Panoptic: Start Evaluation\n",
"-- Got MatchedInstancePair, will evaluate instances\n",
"\n",
"+++ MATCHING +++\n",
"Number of instances in reference (num_ref_instances): 22\n",
"Number of instances in prediction (num_pred_instances): 22\n",
"True Positives (tp): 22\n",
"False Positives (fp): 0\n",
"False Negatives (fn): 0\n",
"Recognition Quality / F1-Score (rq): 1.0\n",
"\n",
"+++ GLOBAL +++\n",
"Global Binary Dice (global_bin_dsc): 0.9744370224078394\n",
"Global Binary Centerline Dice (global_bin_cldsc): 0.9637064011802574\n",
"Global Binary Average Symmetric Surface Distance (global_bin_assd): 0.1499152780072207\n",
"Global Binary Relative Volume Difference (global_bin_rvd): -0.0006011763989268869\n",
"\n",
"+++ INSTANCE +++\n",
"Segmentation Quality IoU (sq): 0.8328184295330796 +- 0.15186064004517466\n",
"Panoptic Quality IoU (pq): 0.8328184295330796\n",
"Segmentation Quality Dsc (sq_dsc): 0.900292616009954 +- 0.10253566174957332\n",
"Panoptic Quality Dsc (pq_dsc): 0.900292616009954\n",
"Segmentation Quality Assd (sq_assd): 0.250331887879225 +- 0.07696680402317076\n",
"Segmentation Quality Relative Volume Difference (sq_rvd): 0.0028133049062930553 +- 0.034518928495505724\n",
"\n"
]
}
],
"source": [
"# Now use it as normal\n",
"result, debug_data = evaluator.evaluate(pred_masks, ref_masks)[\"ungrouped\"]\n",
"print(result) # yields same results as the evaluator object manually constructed"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "helm",
"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.11.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading

0 comments on commit 98e3fcf

Please sign in to comment.