{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Load Libs","metadata":{}},{"cell_type":"code","source":"import sys\n\nsys.path.append('../input/monai-v081/')","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:16:30.854598Z","iopub.execute_input":"2022-07-14T17:16:30.854893Z","iopub.status.idle":"2022-07-14T17:16:30.859465Z","shell.execute_reply.started":"2022-07-14T17:16:30.854862Z","shell.execute_reply":"2022-07-14T17:16:30.858593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\nfrom glob import glob\nimport os\nimport numpy as np\nimport pandas as pd\nimport torch\nfrom torch import nn\nfrom monai.inferers import sliding_window_inference\nfrom monai.data import decollate_batch\nfrom monai.handlers.utils import from_engine\nfrom monai.networks.nets import UNet, AttentionUnet\nfrom torch.cuda.amp import GradScaler, autocast\nfrom tqdm import tqdm\nimport json","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:16:30.867666Z","iopub.execute_input":"2022-07-14T17:16:30.868368Z","iopub.status.idle":"2022-07-14T17:16:30.876047Z","shell.execute_reply.started":"2022-07-14T17:16:30.868332Z","shell.execute_reply":"2022-07-14T17:16:30.875152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from monai.data import CacheDataset, DataLoader\nfrom monai.transforms import (\n    Compose,\n    Activations,\n    AsDiscrete,\n    Activationsd,\n    AsDiscreted,\n    KeepLargestConnectedComponentd,\n    Invertd,\n    LoadImage,\n    Transposed,\n    LoadImaged,\n    AddChanneld,\n    CastToTyped,\n    Lambdad,\n    Resized,\n    EnsureTyped,\n    SpatialPadd,\n    EnsureChannelFirstd,\n)","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:16:30.880249Z","iopub.execute_input":"2022-07-14T17:16:30.880965Z","iopub.status.idle":"2022-07-14T17:16:30.891706Z","shell.execute_reply.started":"2022-07-14T17:16:30.880919Z","shell.execute_reply":"2022-07-14T17:16:30.890261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prepare meta info.","metadata":{}},{"cell_type":"markdown","source":"### Thanks awsaf49, this section refers to:\nhttps://www.kaggle.com/code/awsaf49/uwmgi-2-5d-infer-pytorch","metadata":{}},{"cell_type":"code","source":"def get_metadata(row):\n    data = row['id'].split('_')\n    case = int(data[0].replace('case',''))\n    day = int(data[1].replace('day',''))\n    slice_ = int(data[-1])\n    row['case'] = case\n    row['day'] = day\n    row['slice'] = slice_\n    return row\n\ndef path2info(row):\n    path = row['image_path']\n    data = path.split('/')\n    slice_ = int(data[-1].split('_')[1])\n    case = int(data[-3].split('_')[0].replace('case',''))\n    day = int(data[-3].split('_')[1].replace('day',''))\n    width = int(data[-1].split('_')[2])\n    height = int(data[-1].split('_')[3])\n    row['height'] = height\n    row['width'] = width\n    row['case'] = case\n    row['day'] = day\n    row['slice'] = slice_\n    return row","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:16:30.893655Z","iopub.execute_input":"2022-07-14T17:16:30.894405Z","iopub.status.idle":"2022-07-14T17:16:30.906104Z","shell.execute_reply.started":"2022-07-14T17:16:30.894304Z","shell.execute_reply":"2022-07-14T17:16:30.905260Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = pd.read_csv('../input/uw-madison-gi-tract-image-segmentation/sample_submission.csv')\nif not len(sub_df):\n    debug = True\n    sub_df = pd.read_csv('../input/uw-madison-gi-tract-image-segmentation/train.csv')[:1000*3]\n    sub_df = sub_df.drop(columns=['class','segmentation']).drop_duplicates()\nelse:\n    debug = False\n    sub_df = sub_df.drop(columns=['class','predicted']).drop_duplicates()\nsub_df = sub_df.apply(lambda x: get_metadata(x),axis=1)","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:16:30.907972Z","iopub.execute_input":"2022-07-14T17:16:30.908545Z","iopub.status.idle":"2022-07-14T17:16:32.714786Z","shell.execute_reply.started":"2022-07-14T17:16:30.908505Z","shell.execute_reply":"2022-07-14T17:16:32.714000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if debug:\n    paths = glob(f'/kaggle/input/uw-madison-gi-tract-image-segmentation/train/**/*png',recursive=True)\n#     paths = sorted(paths)\nelse:\n    paths = glob(f'/kaggle/input/uw-madison-gi-tract-image-segmentation/test/**/*png',recursive=True)\n#     paths = sorted(paths)\npath_df = pd.DataFrame(paths, columns=['image_path'])\npath_df = path_df.apply(lambda x: path2info(x),axis=1)\npath_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:16:32.716503Z","iopub.execute_input":"2022-07-14T17:16:32.716793Z","iopub.status.idle":"2022-07-14T17:18:11.889533Z","shell.execute_reply.started":"2022-07-14T17:16:32.716755Z","shell.execute_reply":"2022-07-14T17:18:11.888650Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Produce 3d data list for MONAI DataSet","metadata":{}},{"cell_type":"code","source":"test_df = sub_df.merge(path_df, on=['case','day','slice'], how='left')\ntest_df[\"case_id_str\"] = test_df[\"id\"].apply(lambda x: x.split(\"_\", 2)[0])\ntest_df[\"day_num_str\"] = test_df[\"id\"].apply(lambda x: x.split(\"_\", 2)[1])\ntest_df[\"slice_id\"] = test_df[\"id\"].apply(lambda x: x.split(\"_\", 2)[2])","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:18:11.891100Z","iopub.execute_input":"2022-07-14T17:18:11.891679Z","iopub.status.idle":"2022-07-14T17:18:11.915462Z","shell.execute_reply.started":"2022-07-14T17:18:11.891635Z","shell.execute_reply":"2022-07-14T17:18:11.914776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = []\n\nfor group in test_df.groupby([\"case_id_str\", \"day_num_str\"]):\n\n    case_id_str, day_num_str = group[0]\n    group_id = case_id_str + \"_\" + day_num_str\n    group_df = group[1].sort_values(\"slice_id\", ascending=True)\n    n_slices = group_df.shape[0]\n    group_slices, group_ids = [], []\n    for idx in range(n_slices):\n        slc = group_df.iloc[idx]\n        group_slices.append(slc.image_path)\n        group_ids.append(slc.id)\n    test_data.append({\"image\": group_slices, \"id\": group_ids})","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:18:11.917828Z","iopub.execute_input":"2022-07-14T17:18:11.918170Z","iopub.status.idle":"2022-07-14T17:18:12.066576Z","shell.execute_reply.started":"2022-07-14T17:18:11.918124Z","shell.execute_reply":"2022-07-14T17:18:12.065843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prepare Transforms, Dataset, DataLoader","metadata":{}},{"cell_type":"code","source":"# glob(\"../input/uw-dc-c-120proc-20220714170505/*/best_weights*\")","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:18:12.067921Z","iopub.execute_input":"2022-07-14T17:18:12.068185Z","iopub.status.idle":"2022-07-14T17:18:12.074705Z","shell.execute_reply.started":"2022-07-14T17:18:12.068150Z","shell.execute_reply":"2022-07-14T17:18:12.073939Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class cfg:\n    img_size = (224, 224, 80)\n    in_channels = 1\n    out_channels = 3\n    device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n\n    weights = glob(\"../input/uw-dc-c-120proc-20220714170505/*/best_weights*\")\n    batch_size = 1\n    sw_batch_size = 2","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:18:12.076335Z","iopub.execute_input":"2022-07-14T17:18:12.076640Z","iopub.status.idle":"2022-07-14T17:18:12.088675Z","shell.execute_reply.started":"2022-07-14T17:18:12.076601Z","shell.execute_reply":"2022-07-14T17:18:12.087954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_transforms = Compose(\n    [\n        LoadImaged(keys=\"image\"), # d, h, w\n        AddChanneld(keys=\"image\"), # c, d, h, w\n        Transposed(keys=\"image\", indices=[0, 2, 3, 1]), # c, w, h, d\n        Lambdad(keys=\"image\", func=lambda x: x / x.max()),\n#         SpatialPadd(keys=\"image\", spatial_size=cfg.img_size),  # in case less than 80 slices\n        EnsureTyped(keys=\"image\", dtype=torch.float32),\n    ]\n)\n\ntest_ds = CacheDataset(\n        data=test_data,\n        transform=test_transforms,\n        cache_rate=0.0,\n        num_workers=2,\n    )\n\ntest_dataloader = DataLoader(\n    test_ds,\n    batch_size=cfg.batch_size,\n    num_workers=2,\n    pin_memory=True,\n)","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:18:12.090210Z","iopub.execute_input":"2022-07-14T17:18:12.090563Z","iopub.status.idle":"2022-07-14T17:18:12.099154Z","shell.execute_reply.started":"2022-07-14T17:18:12.090523Z","shell.execute_reply":"2022-07-14T17:18:12.098193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prepare Network","metadata":{}},{"cell_type":"code","source":"model = AttentionUnet(\n    spatial_dims=3,\n    in_channels=1,\n    out_channels=3,\n    channels=(32, 64, 128, 256, 512),\n    strides=(2, 2, 2, 2),\n    kernel_size=3,\n    up_kernel_size=3,\n    dropout=0.2,\n).to(cfg.device)","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:18:12.100549Z","iopub.execute_input":"2022-07-14T17:18:12.101440Z","iopub.status.idle":"2022-07-14T17:18:12.369251Z","shell.execute_reply.started":"2022-07-14T17:18:12.101402Z","shell.execute_reply":"2022-07-14T17:18:12.368469Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Infer","metadata":{}},{"cell_type":"code","source":"# ref.: https://www.kaggle.com/stainsby/fast-tested-rle\ndef rle_encode(img):\n    \"\"\" TBD\n    \n    Args:\n        img (np.array): \n            - 1 indicating mask\n            - 0 indicating background\n    \n    Returns: \n        run length as string formated\n    \"\"\"\n    \n    pixels = img.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:18:12.370843Z","iopub.execute_input":"2022-07-14T17:18:12.371347Z","iopub.status.idle":"2022-07-14T17:18:12.378554Z","shell.execute_reply.started":"2022-07-14T17:18:12.371308Z","shell.execute_reply":"2022-07-14T17:18:12.377841Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"outputs = []\n\npost_pred = Compose([\n    Activations(sigmoid=True),\n    AsDiscrete(threshold=0.44),\n])\n\nmodel.eval()\ntorch.set_grad_enabled(False)\nprogress_bar = tqdm(range(len(test_dataloader)))\nval_it = iter(test_dataloader)\nfor itr in progress_bar:\n    batch = next(val_it)\n    test_inputs = batch[\"image\"].to(cfg.device)\n\n    pred_all = []\n    for weights in cfg.weights:\n        print(\"[DEBUG][LoadModel]\", weights)\n        model.load_state_dict(torch.load(weights,map_location='cuda:0')[\"model\"])\n        pred = sliding_window_inference(test_inputs, cfg.img_size, cfg.sw_batch_size, model)\n        pred_all.append(pred)\n        # do 4 tta\n        for dims in [[2], [3], [2, 3]]:\n            flip_pred = sliding_window_inference(torch.flip(test_inputs, dims=dims), cfg.img_size, cfg.sw_batch_size, model)\n            flip_pred = torch.flip(flip_pred, dims=dims)\n            pred_all.append(flip_pred)\n    \n    pred_all = torch.mean(torch.stack(pred_all), dim=0)[0]\n    pred_all = post_pred(pred_all)\n    # c, w, h, d to d, c, h, w\n    pred_all = torch.permute(pred_all, [3, 0, 2, 1]).cpu().numpy().astype(np.uint8)\n    id_outputs = from_engine([\"id\"])(batch)[0]\n\n    for test_output, id_output in zip(pred_all, id_outputs):\n        id_name = id_output[0]\n        lb, sb, st = test_output\n        outputs.append([id_name, \"large_bowel\", rle_encode(lb)])\n        outputs.append([id_name, \"small_bowel\", rle_encode(sb)])\n        outputs.append([id_name, \"stomach\", rle_encode(st)])\n        \n        torch.cuda.empty_cache()\n        gc.collect()\n","metadata":{"execution":{"iopub.status.busy":"2022-07-14T17:18:12.381778Z","iopub.execute_input":"2022-07-14T17:18:12.382065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submit = pd.DataFrame(data=np.array(outputs), columns=[\"id\", \"class\", \"predicted\"])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fix sub error, refers to: https://www.kaggle.com/competitions/uw-madison-gi-tract-image-segmentation/discussion/320541\nif not debug:\n    sub_df = pd.read_csv('../input/uw-madison-gi-tract-image-segmentation/sample_submission.csv')\n    del sub_df['predicted']\n    sub_df = sub_df.merge(submit, on=['id','class'])\n    sub_df.to_csv('submission.csv',index=False)\nelse:\n    submit.to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}