Skip to content

Commit

Permalink
Minor fixes related to infer and others (#1773)
Browse files Browse the repository at this point in the history
Signed-off-by: Sachidanand Alle <[email protected]>
  • Loading branch information
SachidanandAlle authored Nov 4, 2024
1 parent 029e9ac commit 089acd0
Show file tree
Hide file tree
Showing 13 changed files with 80 additions and 52 deletions.
36 changes: 34 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,38 @@ __pycache__
.vscode

Dockerfile
sample-apps/**/model
node_modules
.webpack

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
.venv/
ubuntu_venv/

# apps
sample-apps/*/logs
sample-apps/*/train
sample-apps/*/model

# docs build
docs/build
docs/source/apidocs

# MONAI-label
*.nii.gz
.DS_Store
*.DS_Store
bin
junit
test-output.xml
studies
tests/data

# Packages
node_modules
yarn.lock
10 changes: 3 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ venv/
ENV/
env.bak/
venv.bak/
.venv/
ubuntu_venv/

# Spyder project settings
.spyderproject
Expand All @@ -139,12 +141,6 @@ dmypy.json
# Pyre type checker
.pyre/

# virtualenv
.venv/
venv/
ENV/
ubuntu_venv/

# IDE
.idea/
.vscode/
Expand All @@ -166,7 +162,7 @@ junit
test-output.xml
studies
tests/data
yarn.lock

# Packages
node_modules
yarn.lock
4 changes: 4 additions & 0 deletions monailabel/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ def infer(self, model, image_id, params, label_in=None, file=None, session_id=No
fields = {"params": json.dumps(params) if params else "{}"}
files = {"label": label_in} if label_in else {}
files.update({"file": file} if file and not session_id else {})
logger.info(f"Files: {files}")

status, form, files, _ = MONAILabelUtils.http_multipart(
"POST", self._server_url, selector, fields, files, headers=self._headers
Expand Down Expand Up @@ -584,6 +585,9 @@ def send_response(conn, content_type="application/json"):

@staticmethod
def save_result(files, tmpdir):
if not files:
return None

for name in files:
data = files[name]
result_file = os.path.join(tmpdir, name)
Expand Down
6 changes: 2 additions & 4 deletions monailabel/endpoints/infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,8 @@ def send_response(datastore, result, output, background_tasks):
if output == "json":
return res_json

m_type = get_mime_type(res_img)

if output == "image":
return FileResponse(res_img, media_type=m_type, filename=os.path.basename(res_img))
return FileResponse(res_img, media_type=get_mime_type(res_img), filename=os.path.basename(res_img))

if output == "dicom_seg":
res_dicom_seg = result.get("dicom_seg")
Expand All @@ -106,7 +104,7 @@ def send_response(datastore, result, output, background_tasks):
res_fields = dict()
res_fields["params"] = (None, json.dumps(res_json), "application/json")
if res_img and os.path.exists(res_img):
res_fields["image"] = (os.path.basename(res_img), open(res_img, "rb"), m_type)
res_fields["image"] = (os.path.basename(res_img), open(res_img, "rb"), get_mime_type(res_img))
else:
logger.info(f"Return only Result Json as Result Image is not available: {res_img}")
return res_json
Expand Down
2 changes: 1 addition & 1 deletion monailabel/interfaces/tasks/infer_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,5 @@ def is_valid(self) -> bool:
pass

@abstractmethod
def __call__(self, request) -> Union[Dict, Tuple[str, Dict[str, Any]]]:
def __call__(self, request) -> Tuple[Union[str, None], Dict]:
pass
8 changes: 4 additions & 4 deletions monailabel/tasks/infer/basic_infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from monailabel.interfaces.utils.transform import dump_data, run_transforms
from monailabel.transform.cache import CacheTransformDatad
from monailabel.transform.writer import ClassificationWriter, DetectionWriter, Writer
from monailabel.utils.others.generic import device_list, device_map, name_to_device
from monailabel.utils.others.generic import device_list, device_map, name_to_device, strtobool

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -253,7 +253,7 @@ def detector(self, data=None) -> Optional[Callable]:

def __call__(
self, request, callbacks: Union[Dict[CallBackTypes, Any], None] = None
) -> Union[Dict, Tuple[str, Dict[str, Any]]]:
) -> Tuple[Union[str, None], Dict]:
"""
It provides basic implementation to run the following in order
- Run Pre Transforms
Expand Down Expand Up @@ -322,8 +322,8 @@ def __call__(
data = callback_run_post_transforms(data)
latency_post = time.time() - start

if self.skip_writer:
return dict(data)
if self.skip_writer or strtobool(data.get("skip_writer")):
return None, dict(data)

start = time.time()
result_file_name, result_json = self.writer(data)
Expand Down
42 changes: 17 additions & 25 deletions monailabel/tasks/infer/bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,14 @@ def __init__(

# labels = ({v.lower(): int(k) for k, v in pred.get("channel_def", {}).items() if v.lower() != "background"})
labels = {}
type = self._get_type(os.path.basename(path), type)
for k, v in pred.get("channel_def", {}).items():
if (not type.lower() == "deepedit") and (v.lower() != "background"):
labels[v.lower()] = int(k)
else:
logger.info(f"Model: {os.path.basename(path)}; Type: {type}; Label: {v} => {k}")
if v.lower() != "background" or type.lower() == "deepedit":
labels[v.lower()] = int(k)
description = metadata.get("description")
spatial_shape = image.get("spatial_shape")
dimension = len(spatial_shape) if spatial_shape else 3
type = self._get_type(os.path.basename(path), type)

# if detection task, set post restore to False by default.
self.add_post_restore = False if type == "detection" else add_post_restore
Expand Down Expand Up @@ -273,28 +272,21 @@ def post_transforms(self, data=None) -> Sequence[Callable]:
return post

def _get_type(self, name, type):
if type:
return type

name = name.lower() if name else ""
return (
(
InferType.DEEPEDIT
if "deepedit" in name
else (
InferType.DEEPGROW
if "deepgrow" in name
else (
InferType.DETECTION
if "detection" in name
else (
InferType.SEGMENTATION
if "segmentation" in name
else InferType.CLASSIFICATION if "classification" in name else InferType.SEGMENTATION
)
)
)
)
if not type
else type
)
if "deepedit" in name:
return InferType.DEEPEDIT
if "deepgrow" in name:
return InferType.DEEPGROW
if "detection" in name:
return InferType.DETECTION
if "segmentation" in name:
return InferType.SEGMENTATION
if "classification" in name:
return InferType.CLASSIFICATION
return InferType.SEGMENTATION

def _filter_transforms(self, transforms, filters):
if not filters or not transforms:
Expand Down
2 changes: 1 addition & 1 deletion monailabel/tasks/scoring/epistemic_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def run_scoring(self, image_id, simulation_size, model_ts, datastore):

accum_unl_outputs = []
for i in range(simulation_size):
data = self.infer_task(request=request)
_, data = self.infer_task(request=request)
pred = data[self.infer_task.output_label_key] if isinstance(data, dict) else None
if pred is not None:
logger.debug(f"EPISTEMIC:: {image_id} => {i} => pred: {pred.shape}; sum: {np.sum(pred)}")
Expand Down
2 changes: 1 addition & 1 deletion monailabel/transform/post.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def __call__(self, data):
spatial_size = spatial_shape[-len(current_size) :]

# Undo Spacing
if torch.any(torch.Tensor(np.not_equal(current_size, spatial_size))):
if np.any(np.not_equal(current_size, spatial_size)):
resizer = Resize(spatial_size=spatial_size, mode=self.mode[idx])
result = resizer(result, mode=self.mode[idx], align_corners=self.align_corners[idx])

Expand Down
6 changes: 3 additions & 3 deletions monailabel/utils/others/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ def _list_files(d, ext):
]


def strtobool(str):
return bool(distutils.util.strtobool(str))
def strtobool(s):
return False if s is None else s if isinstance(s, bool) else bool(distutils.util.strtobool(s))


def is_openslide_supported(name):
Expand Down Expand Up @@ -336,7 +336,7 @@ def get_bundle_models(app_dir, conf, conf_key="models"):
zoo_source = conf.get("zoo_source", settings.MONAI_ZOO_SOURCE)

models = conf.get(conf_key)
models = models.split(",")
models = models.split(",") if models else []
models = [m.strip() for m in models]

if zoo_source == "monaihosting": # if in github env, access model zoo
Expand Down
2 changes: 1 addition & 1 deletion monailabel/utils/others/pathology.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def create_asap_annotations_xml(json_data, loglevel="INFO"):
label = element["label"]
color = to_hex(color_map.get(label))

logger.info(f"Adding Contours for label: {label}; color: {color}; color_map: {color_map}")
logger.debug(f"Adding Contours for label: {label}; color: {color}; color_map: {color_map}")
labels[label] = color

contours = element["contours"]
Expand Down
9 changes: 7 additions & 2 deletions sample-apps/endoscopy/lib/infers/deepedit.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,21 @@ def inferer(self, data=None) -> Inferer:
return SimpleInferer()

def post_transforms(self, data=None) -> Sequence[Callable]:
return [
t = [
EnsureTyped(keys="pred", device=data.get("device") if data else None),
Activationsd(keys="pred", sigmoid=True),
AsDiscreted(keys="pred", threshold=0.5),
Restored(keys="pred", ref_image="image"),
SqueezeDimd(keys="pred"),
ToNumpyd(keys="pred", dtype=np.uint8),
FindContoursd(keys="pred", labels=self.labels, key_foreground_points="foreground"),
]
if data and data.get("output") == "mask":
return t
t.append(FindContoursd(keys="pred", labels=self.labels, key_foreground_points="foreground"))
return t

def writer(self, data, extension=None, dtype=None):
if data and data.get("output") == "mask":
return super().writer(data, extension=extension, dtype=dtype)
writer = PolygonWriter(label=self.output_label_key, json=self.output_json_key)
return writer(data)
3 changes: 2 additions & 1 deletion sample-apps/radiology/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
from monailabel.interfaces.tasks.scoring import ScoringMethod
from monailabel.interfaces.tasks.strategy import Strategy
from monailabel.interfaces.tasks.train import TrainTask
from monailabel.scribbles.infer import GMMBasedGraphCut, HistogramBasedGraphCut
from monailabel.tasks.activelearning.first import First
from monailabel.tasks.activelearning.random import Random

Expand Down Expand Up @@ -141,6 +140,8 @@ def init_infers(self) -> Dict[str, InferTask]:
# Scribbles
#################################################
if self.scribbles:
from monailabel.scribbles.infer import GMMBasedGraphCut, HistogramBasedGraphCut

infers.update(
{
"Histogram+GraphCut": HistogramBasedGraphCut(
Expand Down

0 comments on commit 089acd0

Please sign in to comment.