Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why did I get a higher FROC than in the paper #6

Open
jjjjjjjjj58 opened this issue Feb 15, 2025 · 1 comment
Open

Why did I get a higher FROC than in the paper #6

jjjjjjjjj58 opened this issue Feb 15, 2025 · 1 comment

Comments

@jjjjjjjjj58
Copy link

I used your code to run the results in DBTex, but got a higher FROC. What's the reason for this? For example, this is the result for BYU_BTEAM:
{'sensitivity_at_2_fps_all': 0.9632352941176471, 'sensitivity_at_1_fps_positive': 0.9382352941176471, 'sensitivity_at_2_fps_positive': 0.9705882352941176, 'sensitivity_at_3_fps_positive': 0.9705882352941176, 'sensitivity_at_4_fps_positive': 0.9779411764705882, 'mean_sensitivity_positive': 0.9643382352941177}

The result in the paper was 95.7 and I got 96.43.
Thx.

@jjjjjjjjj58
Copy link
Author

Here's the full code, I didn't make any changes to it:# https://github.com/MaciejMazurowski/duke-dbt-data/blob/master/duke_dbt_data.py
from typing import AnyStr, BinaryIO, Dict, List, NamedTuple, Optional, Union
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
import pandas as pd
import pydicom as dicom
from skimage.exposure import rescale_intensity

from typing import AnyStr, BinaryIO, Dict, List, NamedTuple, Optional, Union

import matplotlib
import numpy as np
import pandas as pd
import pydicom as dicom
from skimage.exposure import rescale_intensity

def evaluate(
labels_fp: pd._typing.BaseBuffer,
boxes_fp: pd._typing.BaseBuffer,
predictions_fp: pd._typing.BaseBuffer,
) -> Dict[str, float]:
"""Evaluate predictions"""
df_labels = pd.read_csv(labels_fp)
df_boxes = pd.read_csv(boxes_fp, dtype={"VolumeSlices": float})
df_pred = pd.read_csv(predictions_fp, dtype={"Score": float})

df_labels = df_labels.reset_index().set_index(["StudyUID", "View"]).sort_index()
df_boxes = df_boxes.reset_index().set_index(["StudyUID", "View"]).sort_index()
df_pred = df_pred.reset_index().set_index(["StudyUID", "View"]).sort_index()

df_pred["TP"] = 0
df_pred["GTID"] = -1

thresholds = [df_pred["Score"].max() + 1.0]

# find true positive predictions and assign detected ground truth box ID
for box_pred in df_pred.itertuples():
    if box_pred.Index not in df_boxes.index:
        continue

    df_boxes_view = df_boxes.loc[[box_pred.Index]]
    view_slice_offset = df_boxes.loc[[box_pred.Index], "VolumeSlices"].iloc[0] / 4
    tp_boxes = [
        b
        for b in df_boxes_view.itertuples()
        if _is_tp(box_pred, b, slice_offset=view_slice_offset)
    ]
    if len(tp_boxes) > 1:
        # find the nearest GT box
        tp_distances = [_distance(box_pred, b) for b in tp_boxes]
        tp_boxes = [tp_boxes[np.argmin(tp_distances)]]
    if len(tp_boxes) > 0:
        tp_i = tp_boxes[0].index
        df_pred.loc[df_pred["index"] == box_pred.index, ("TP", "GTID")] = (1, tp_i)
        thresholds.append(box_pred.Score)

thresholds.append(df_pred["Score"].min() - 1.0)

# compute sensitivity at 2 FPs/volume on all cases
evaluation_fps_all = (2.0,)
tpr_all = _froc(
    df_pred=df_pred,
    thresholds=thresholds,
    n_volumes=len(df_labels),
    n_boxes=len(df_boxes),
    evaluation_fps=evaluation_fps_all,
)
result = {f"sensitivity_at_2_fps_all": tpr_all[0]}

# compute mean sensitivity at 1, 2, 3, 4 FPs/volume on positive cases
df_pred = df_pred[df_pred.index.isin(df_boxes.index)]
df_labels = df_labels[df_labels.index.isin(df_boxes.index)]
evaluation_fps_positive = (1.0, 2.0, 3.0, 4.0)
tpr_positive = _froc(
    df_pred=df_pred,
    thresholds=thresholds,
    n_volumes=len(df_labels),
    n_boxes=len(df_boxes),
    evaluation_fps=evaluation_fps_positive,
)

result.update(
    dict(
        (f"sensitivity_at_{int(x)}_fps_positive", y)
        for x, y in zip(evaluation_fps_positive, tpr_positive)
    )
)
result.update({"mean_sensitivity_positive": np.mean(tpr_positive)})

return result

def _froc(
df_pred: pd.DataFrame,
thresholds: List[float],
n_volumes: int,
n_boxes: int,
evaluation_fps: tuple,
) -> List[float]:
tpr = []
fps = []
for th in sorted(thresholds, reverse=True):
df_th = df_pred.loc[df_pred["Score"] >= th]
df_th_unique_tp = df_th.reset_index().drop_duplicates(
subset=["StudyUID", "View", "TP", "GTID"]
)
n_tps_th = float(sum(df_th_unique_tp["TP"]))
tpr_th = n_tps_th / n_boxes
n_fps_th = float(len(df_th[df_th["TP"] == 0]))
fps_th = n_fps_th / n_volumes
tpr.append(tpr_th)
fps.append(fps_th)
if fps_th > max(evaluation_fps):
break
return [np.interp(x, fps, tpr) for x in evaluation_fps]

def _is_tp(
box_pred: NamedTuple, box_true: NamedTuple, slice_offset: int, min_dist: int = 100
) -> bool:
pred_y = box_pred.Y + box_pred.Height / 2
pred_x = box_pred.X + box_pred.Width / 2
pred_z = box_pred.Z + box_pred.Depth / 2
true_y = box_true.Y + box_true.Height / 2
true_x = box_true.X + box_true.Width / 2
true_z = box_true.Slice
# 2D distance between true and predicted center points
dist = np.linalg.norm((pred_x - true_x, pred_y - true_y))
# compute radius based on true box size
dist_threshold = np.sqrt(box_true.Width ** 2 + box_true.Height ** 2) / 2.0
dist_threshold = max(dist_threshold, min_dist)
slice_diff = np.abs(pred_z - true_z)
# TP if predicted center within radius and slice within slice offset
return dist <= dist_threshold and slice_diff <= slice_offset

def _distance(box_pred: NamedTuple, box_true: NamedTuple) -> float:
pred_y = box_pred.Y + box_pred.Height / 2
pred_x = box_pred.X + box_pred.Width / 2
pred_z = box_pred.Z + box_pred.Depth / 2
true_y = box_true.Y + box_true.Height / 2
true_x = box_true.X + box_true.Width / 2
true_z = box_true.Slice
return np.linalg.norm((pred_x - true_x, pred_y - true_y, pred_z - true_z))

path = r'D:\pycharm project\dataset\dbt duke\manifest-1617905855234'
result=evaluate(path+'\BCS-DBT-labels-test.csv',path+'\BCS-DBT-boxes-test.csv',r'D:\pycharm project\dataset\dbt duke\manifest-1617905855234\team_predictions_bothphases\phase2\test/nyu_bteam.csv')
print(result)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant