def save_label( background_tasks: BackgroundTasks, image: str, params: str = Form("{}"), tag: str = DefaultLabelTag.FINAL.value, label: UploadFile = File(...), ): file_ext = "".join(pathlib.Path( label.filename).suffixes) if label.filename else ".nii.gz" label_file = tempfile.NamedTemporaryFile(suffix=file_ext).name tag = tag if tag else DefaultLabelTag.FINAL.value with open(label_file, "wb") as buffer: shutil.copyfileobj(label.file, buffer) background_tasks.add_task(remove_file, label_file) instance: MONAILabelApp = app_instance() save_params: Dict[str, Any] = json.loads(params) if params else {} logger.info(f"Save Label params: {params}") label_id = instance.datastore().save_label(image, label_file, tag, save_params) res = instance.on_save_label(image, label_id) res = res if res else {} res.update({ "image": image, "label": label_id, }) return res
def sample(strategy: str, params: Optional[dict] = None): request = {"strategy": strategy} instance: MONAILabelApp = app_instance() config = instance.info().get("config", {}).get("activelearning", {}) request.update(config) params = params if params is not None else {} request.update(params) logger.info(f"Active Learning Request: {request}") result = instance.next_sample(request) if not result: return {} image_id = result["id"] image_info = instance.datastore().get_image_info(image_id) strategy_info = image_info.get("strategy", {}) strategy_info[strategy] = { "ts": int(time.time()), "client_id": params.get("client_id") } instance.datastore().update_image_info(image_id, {"strategy": strategy_info}) result = { "id": image_id, **image_info, } logger.info(f"Next sample: {result}") return result
def run_wsi_inference( background_tasks: BackgroundTasks, model: str, image: str = "", session_id: str = "", wsi: WSIInput = WSIInput(), output: Optional[ResultType] = ResultType.dsa, ): request = {"model": model, "image": image, "output": output.value if output else None} if not image and not session_id: raise HTTPException(status_code=500, detail="Neither Image nor File not Session ID input is provided") instance: MONAILabelApp = app_instance() config = instance.info().get("config", {}).get("infer", {}) request.update(config) request.update(wsi.dict(exclude={"params"})) if wsi.params: request.update(wsi.params) if session_id: session = instance.sessions().get_session(session_id) if session: request["image"] = session.image request["session"] = session.to_json() logger.debug(f"WSI Infer Request: {request}") result = instance.infer_wsi(request) if result is None: raise HTTPException(status_code=500, detail="Failed to execute wsi infer") return send_response(instance.datastore(), result, output, background_tasks)
def run(method: str, request=None, params=None, force_sync=False, enqueue=False): if len(processes(method)) and not enqueue: description = f"++++++++++ {method.capitalize()} Task is Already Running" logger.info(description) return None, description instance = app_instance() config = instance.info().get("config", {}).get(method, {}) request = request if request else {} request.update(config) params = params if params is not None else {} request.update(params) logger.info(f"{method.capitalize()} request: {request}") if force_sync: if method == "batch_infer": return instance.batch_infer(request), None if method == "scoring": return instance.scoring(request), None if method == "train": return instance.train(request), None return run_background_task(request, method), None
def run_inference( background_tasks: BackgroundTasks, model: str, image: str = "", session_id: str = "", params: str = Form("{}"), file: UploadFile = File(None), label: UploadFile = File(None), output: Optional[ResultType] = None, ): request = {"model": model, "image": image} if not file and not image and not session_id: raise HTTPException(status_code=500, detail="Neither Image nor File not Session ID input is provided") instance: MONAILabelApp = app_instance() if file: file_ext = "".join(pathlib.Path(file.filename).suffixes) if file.filename else ".nii.gz" image_file = tempfile.NamedTemporaryFile(suffix=file_ext).name with open(image_file, "wb") as buffer: shutil.copyfileobj(file.file, buffer) request["image"] = image_file background_tasks.add_task(remove_file, image_file) if label: file_ext = "".join(pathlib.Path(label.filename).suffixes) if label.filename else ".nii.gz" label_file = tempfile.NamedTemporaryFile(suffix=file_ext).name with open(label_file, "wb") as buffer: shutil.copyfileobj(label.file, buffer) background_tasks.add_task(remove_file, label_file) # if binary file received, e.g. scribbles from OHIF - then convert using reference image if file_ext == ".bin": image_uri = instance.datastore().get_image_uri(image) label_file = binary_to_image(image_uri, label_file) request["label"] = label_file config = instance.info().get("config", {}).get("infer", {}) request.update(config) p = json.loads(params) if params else {} request.update(p) if session_id: session = instance.sessions().get_session(session_id) if session: request["image"] = session.image request["session"] = session.to_json() logger.info(f"Infer Request: {request}") result = instance.infer(request) if result is None: raise HTTPException(status_code=500, detail="Failed to execute infer") return send_response(instance.datastore(), result, output, background_tasks)
def download_label(label: str, tag: str): instance: MONAILabelApp = app_instance() label = instance.datastore().get_label_uri(label, tag) if not os.path.isfile(label): raise HTTPException(status_code=404, detail="Label NOT Found") return FileResponse(label, media_type=get_mime_type(label), filename=os.path.basename(label))
def download_image(image: str): instance: MONAILabelApp = app_instance() image = instance.datastore().get_image_uri(image) if not os.path.isfile(image): raise HTTPException(status_code=404, detail="Image NOT Found") return FileResponse(image, media_type=get_mime_type(image), filename=os.path.basename(image))
def run(params: Optional[dict] = None, run_sync: Optional[bool] = False): instance: MONAILabelApp = app_instance() result = {} for method in instance.info()["scoring"]: request = {"method": method} if params and params.get(method): request.update(params[method]) res, detail = AsyncTask.run("scoring", request=request, params=params, force_sync=run_sync, enqueue=True) result[method] = {"result": res, "detail": detail} return result
def run(params: Optional[dict] = None, run_sync: Optional[bool] = False): instance: MONAILabelApp = app_instance() result = {} for model in instance.info()["trainers"]: request = {"model": model} if params and params.get(model): request.update(params[model]) res, detail = AsyncTask.run("train", request=request, params=params, force_sync=run_sync, enqueue=True) result[model] = {"result": res, "detail": detail} return result
def datastore(output: Optional[ResultType] = None): d: Datastore = app_instance().datastore() output = output if output else ResultType.stats logger.debug(f"output type: {output}") if output == ResultType.all: return d.json() if output == ResultType.train: return d.datalist() return d.status()
def test_train(args): app = app_instance(app_dir=args.app, studies=args.studies) logger.info(f"Running Training Task: {args.name}") request = { "name": args.name, "device": args.device, "epochs": args.epochs, "amp": args.amp, } app.train(request)
def remove_session(session_id: str): instance: MONAILabelApp = app_instance() sessions: Sessions = instance.sessions() if sessions is None: logger.error("Session Feature is Not Enabled") raise HTTPException(status_code=406, detail="Session Feature is Not Enabled") session_info = sessions.get_session(session_id) if session_info: sessions.remove_session(session_id) return session_info.to_json() raise HTTPException(status_code=404, detail="Session Not Found")
def get_session(session_id: str, update_ts: bool = False, image: bool = False): instance: MONAILabelApp = app_instance() sessions: Sessions = instance.sessions() if sessions is None: logger.error("Session Feature is Not Enabled") raise HTTPException(status_code=406, detail="Session Feature is Not Enabled") session_info = sessions.get_session(session_id, update_ts=update_ts) if session_info: if image: return FileResponse( session_info.image, media_type=get_mime_type(session_info.image), filename=get_basename(session_info.image), ) return session_info.to_json() raise HTTPException(status_code=404, detail=f"Session ({session_id}) Not Found")
def test_info(args): app = app_instance(app_dir=args.app, studies=args.studies) info = app.info() class MyDumper(yaml.Dumper): def increase_indent(self, flow=False, indentless=False): return super().increase_indent(flow, False) yaml.dump( info, sys.stdout, Dumper=MyDumper, sort_keys=False, default_flow_style=False, width=120, indent=2, )
def create_session( background_tasks: BackgroundTasks, uncompress: bool = False, expiry: int = 0, files: List[UploadFile] = File(...), ): instance: MONAILabelApp = app_instance() sessions: Sessions = instance.sessions() if sessions is None: logger.error("Session Feature is Not Enabled") raise HTTPException(status_code=406, detail="Session Feature is Not Enabled") logger.info(f"Uncompress: {uncompress}; Expiry: {expiry}") logger.info(f"Request Files: {files}") received_dir = tempfile.NamedTemporaryFile().name os.makedirs(received_dir, exist_ok=True) input_image = "" total_files = 0 for f in files: basename = get_basename(f.filename) if f.filename else tempfile.NamedTemporaryFile().name input_image = os.path.join(received_dir, basename) with open(input_image, "wb") as fb: shutil.copyfileobj(f.file, fb) total_files += 1 logger.info(f"{total_files} => {f} => {input_image}") if total_files > 1: logger.info(f"Input has multiple files; Saving ALL into: {received_dir}") input_image = received_dir session_id, session_info = sessions.add_session(input_image, expiry, uncompress) background_tasks.add_task(remove_file, received_dir) if total_files == 0: raise HTTPException(status_code=404, detail="Image(s) Not Found") logger.info(f"Session ID: {session_id}; Info: {session_info.to_str()}") return {"session_id": session_id, "session_info": session_info.to_json()}
def add_image( background_tasks: BackgroundTasks, image: Optional[str] = None, params: str = Form("{}"), file: UploadFile = File(...), ): logger.info(f"Image: {image}; File: {file}; params: {params}") file_ext = "".join(pathlib.Path( file.filename).suffixes) if file.filename else ".nii.gz" image_id = image if image else os.path.basename(file.filename).replace( file_ext, "") image_file = tempfile.NamedTemporaryFile(suffix=file_ext).name with open(image_file, "wb") as buffer: shutil.copyfileobj(file.file, buffer) background_tasks.add_task(remove_file, image_file) instance: MONAILabelApp = app_instance() save_params: Dict[str, Any] = json.loads(params) if params else {} image_id = instance.datastore().add_image(image_id, image_file, save_params) return {"image": image_id}
def test_infer(args): app = app_instance(app_dir=args.app, studies=args.studies) logger.info(f"Running Inference Task: {args.model}") response = None for _ in range(args.runs): request = { "model": args.model, "image": args.input, "params": json.loads(args.params), "device": args.device, } response = app.infer(request=request) res_img = response.get("label") res_json = response.get("params") if res_img: result_image = args.output print(f"Move: {res_img} => {result_image}") shutil.move(res_img, result_image) os.chmod(result_image, 0o777) print(f"Check Result file: {result_image}") print(f"Result JSON: {res_json}")
async def startup_event(): instance = app_instance() instance.server_mode(True) instance.on_init_complete()
def app_info(): instance: MONAILabelApp = app_instance() return instance.info()
def remove_image(id: str): instance: MONAILabelApp = app_instance() instance.datastore().remove_image(id) return {}
def remove_label(id: str, tag: str): instance: MONAILabelApp = app_instance() instance.datastore().remove_label(id, tag) return {}