{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":117682,"databundleVersionId":14443416,"sourceType":"competition"},{"sourceId":14068685,"sourceType":"datasetVersion","datasetId":8955007},{"sourceId":14137536,"sourceType":"datasetVersion","datasetId":9009083},{"sourceId":681152,"sourceType":"modelInstanceVersion","modelInstanceId":516822,"modelId":510647},{"sourceId":681333,"sourceType":"modelInstanceVersion","modelInstanceId":516996,"modelId":531656}],"dockerImageVersionId":31193,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# !mkdir whls\n\n# !pip download keras-nightly --dest whls\n# !pip download tifffile imagecodecs --dest whls\n\n# # medic-ai (GitHub)\n# !git clone https://github.com/innat/medic-ai.git\n# !pip install build -q\n# !cd medic-ai && python -m build\n\n# # copy wheel to whls folder\n# !cp medic-ai/dist/*.whl whls/\n# !rm -r /kaggle/working/medic-ai","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install --no-index --find-links=/kaggle/input/xyz-installer/whls \\\n    keras-nightly \\\n    tifffile \\\n    imagecodecs \\\n    medicai\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:23:19.073593Z","iopub.execute_input":"2025-12-13T08:23:19.073907Z","iopub.status.idle":"2025-12-13T08:23:28.384611Z","shell.execute_reply.started":"2025-12-13T08:23:19.073884Z","shell.execute_reply":"2025-12-13T08:23:28.383112Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import medicai\nimport keras\nimport tifffile\nimport imagecodecs\nimport wrapt\n\nprint(\"medicai OK\")\nprint(\"keras:\", keras.__version__)\nprint(\"wrapt:\", wrapt.__version__)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:23:28.386485Z","iopub.execute_input":"2025-12-13T08:23:28.386971Z","iopub.status.idle":"2025-12-13T08:23:49.340993Z","shell.execute_reply.started":"2025-12-13T08:23:28.386938Z","shell.execute_reply":"2025-12-13T08:23:49.339577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nos.environ[\"KERAS_BACKEND\"] = \"jax\"\n\nimport keras\nfrom medicai.transforms import (\n    Compose,\n    ScaleIntensityRange,\n)\nfrom medicai.models import SegFormer, TransUNet\nfrom medicai.utils.inference import SlidingWindowInference\n\nimport numpy as np\nimport pandas as pd\nimport zipfile\nimport tifffile\nfrom matplotlib import pyplot as plt\n\nkeras.config.backend(), keras.version()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:23:49.342545Z","iopub.execute_input":"2025-12-13T08:23:49.343266Z","iopub.status.idle":"2025-12-13T08:23:49.396059Z","shell.execute_reply.started":"2025-12-13T08:23:49.343233Z","shell.execute_reply":"2025-12-13T08:23:49.395098Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"root_dir = \"/kaggle/input/vesuvius-challenge-surface-detection\"\ntest_dir = f\"{root_dir}/test_images\"\noutput_dir = \"/kaggle/working/submission_masks\"\nzip_path = \"/kaggle/working/submission.zip\"\nos.makedirs(output_dir, exist_ok=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:23:49.39719Z","iopub.execute_input":"2025-12-13T08:23:49.397582Z","iopub.status.idle":"2025-12-13T08:23:49.590015Z","shell.execute_reply.started":"2025-12-13T08:23:49.397557Z","shell.execute_reply":"2025-12-13T08:23:49.588653Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_df = pd.read_csv(f\"{root_dir}/test.csv\")\ntest_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:23:49.592205Z","iopub.execute_input":"2025-12-13T08:23:49.592567Z","iopub.status.idle":"2025-12-13T08:23:49.645014Z","shell.execute_reply.started":"2025-12-13T08:23:49.592543Z","shell.execute_reply":"2025-12-13T08:23:49.643736Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def val_transformation(image):\n    data = {\"image\": image}\n    pipeline = Compose([\n        ScaleIntensityRange(\n            keys=[\"image\"],\n            a_min = 0,\n            a_max = 255,\n            b_min = 0,\n            b_max = 1,\n            clip = True,\n        ),\n    ])\n    result = pipeline(data)\n    return result[\"image\"]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:23:49.64618Z","iopub.execute_input":"2025-12-13T08:23:49.646504Z","iopub.status.idle":"2025-12-13T08:23:49.653265Z","shell.execute_reply.started":"2025-12-13T08:23:49.64648Z","shell.execute_reply":"2025-12-13T08:23:49.652184Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"kaggle_model_path = \"/kaggle/input/vsd-model/keras/\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:23:49.6541Z","iopub.execute_input":"2025-12-13T08:23:49.654404Z","iopub.status.idle":"2025-12-13T08:23:49.679233Z","shell.execute_reply.started":"2025-12-13T08:23:49.654382Z","shell.execute_reply":"2025-12-13T08:23:49.678124Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_model():\n    ## LB: 0.486\n    # model = SegFormer(\n    #     input_shape=(128, 128, 128, 1),\n    #     encoder_name='mit_b2',\n    #     classifier_activation='softmax',\n    #     num_classes=2,\n    # )\n    # model.load_weights(\n    #     \"/kaggle/input/vsd-model/keras/segformer.mit.b2/2/segformer.mit.b2.weights.h5\"\n    # )\n\n    ## LB: 0.5 \n    # model = TransUNet(\n    #     input_shape=(128, 128, 128, 1),\n    #     encoder_name='seresnext50',\n    #     classifier_activation='softmax',\n    #     num_classes=2,\n    # )\n    # model.load_weights(\n    #     f\"{kaggle_model_path}/transunet/2/transunet.seresnext50.128px.weights.h5\"\n    # )\n\n    ## LB: 505\n    model = TransUNet(\n        input_shape=(160, 160, 160, 1),\n        encoder_name='seresnext50',\n        classifier_activation='softmax',\n        num_classes=3,\n    )\n    model.load_weights(\n        f\"{kaggle_model_path}/transunet/2/transunet.seresnext50.160px.weights.h5\"\n    )\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:24:07.893651Z","iopub.execute_input":"2025-12-13T08:24:07.893964Z","iopub.status.idle":"2025-12-13T08:24:07.899912Z","shell.execute_reply.started":"2025-12-13T08:24:07.893943Z","shell.execute_reply":"2025-12-13T08:24:07.898764Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = get_model()\nmodel.count_params() / 1e6","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:24:08.48977Z","iopub.execute_input":"2025-12-13T08:24:08.490104Z","iopub.status.idle":"2025-12-13T08:24:17.438097Z","shell.execute_reply.started":"2025-12-13T08:24:08.490081Z","shell.execute_reply":"2025-12-13T08:24:17.436904Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.instance_describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:24:17.439963Z","iopub.execute_input":"2025-12-13T08:24:17.440319Z","iopub.status.idle":"2025-12-13T08:24:17.54998Z","shell.execute_reply.started":"2025-12-13T08:24:17.440268Z","shell.execute_reply":"2025-12-13T08:24:17.548634Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"swi = SlidingWindowInference(\n    model,\n    num_classes=3,\n    roi_size=(160, 160, 160),\n    sw_batch_size=1,\n    mode='gaussian',\n    overlap=0.5,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:24:17.551093Z","iopub.execute_input":"2025-12-13T08:24:17.551471Z","iopub.status.idle":"2025-12-13T08:24:17.556807Z","shell.execute_reply.started":"2025-12-13T08:24:17.551442Z","shell.execute_reply":"2025-12-13T08:24:17.555621Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_volume(path):\n    vol = tifffile.imread(path)\n    vol = vol.astype(np.float32)\n    vol = vol[None, ..., None]\n    return vol\n\ndef predict(sample):\n    mask = swi(sample)\n    output = mask.argmax(-1).astype(np.uint8).squeeze()\n    return output","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:24:17.558533Z","iopub.execute_input":"2025-12-13T08:24:17.558814Z","iopub.status.idle":"2025-12-13T08:24:17.578672Z","shell.execute_reply.started":"2025-12-13T08:24:17.558793Z","shell.execute_reply":"2025-12-13T08:24:17.577149Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with zipfile.ZipFile(\n    zip_path, \"w\", compression=zipfile.ZIP_DEFLATED\n) as z:\n    for image_id in test_df[\"id\"]:\n        tif_path = f\"{test_dir}/{image_id}.tif\"\n        \n        volume = load_volume(tif_path)\n        volume = val_transformation(volume)\n        output = predict(volume) \n        \n        out_path = f\"{output_dir}/{image_id}.tif\"\n        tifffile.imwrite(out_path, output.astype(np.uint8))\n\n        z.write(out_path, arcname=f\"{image_id}.tif\")\n        os.remove(out_path)\n\nprint(\"Submission ZIP:\", zip_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-13T08:24:17.579754Z","iopub.execute_input":"2025-12-13T08:24:17.580037Z","iopub.status.idle":"2025-12-13T08:37:56.286377Z","shell.execute_reply.started":"2025-12-13T08:24:17.580011Z","shell.execute_reply":"2025-12-13T08:37:56.28534Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}