{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":117682,"databundleVersionId":15062069,"sourceType":"competition"}],"dockerImageVersionId":31234,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"pip install numpy tifffile scipy scikit-image pandas tqdm imagecodecs","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T14:57:53.351272Z","iopub.execute_input":"2025-12-24T14:57:53.351601Z","iopub.status.idle":"2025-12-24T14:58:00.266431Z","shell.execute_reply.started":"2025-12-24T14:57:53.351559Z","shell.execute_reply":"2025-12-24T14:58:00.265306Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport glob\nimport numpy as np\nimport tifffile\nimport pandas as pd\nfrom scipy.ndimage import distance_transform_edt\nfrom skimage.morphology import skeletonize\nfrom joblib import Parallel, delayed\nfrom tqdm import tqdm\nimport imagecodecs","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-24T14:58:00.268889Z","iopub.execute_input":"2025-12-24T14:58:00.269236Z","iopub.status.idle":"2025-12-24T14:58:01.481769Z","shell.execute_reply.started":"2025-12-24T14:58:00.269201Z","shell.execute_reply":"2025-12-24T14:58:01.480715Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# ================= CONFIGURATION =================\nINPUT_FOLDER = \"/kaggle/input/vesuvius-challenge-surface-detection/train_labels\"\nOUTPUT_CSV = \"sheet_thickness_results.csv\"\nNUM_WORKERS = 4  # -1 uses all available cores\nDOWNSAMPLE_RATE = 2\n# =================================================","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T14:58:01.482860Z","iopub.execute_input":"2025-12-24T14:58:01.483422Z","iopub.status.idle":"2025-12-24T14:58:01.489900Z","shell.execute_reply.started":"2025-12-24T14:58:01.483371Z","shell.execute_reply":"2025-12-24T14:58:01.488823Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def process_3d_volume(filepath):\n        # 1. Load 3D Volume\n        vol = tifffile.imread(filepath)\n        \n        # Ensure it's 3D (Depth, Height, Width)\n        # If it has 4 dims (e.g. Channel dim), squeeze it\n        vol = np.squeeze(vol)\n        if vol.ndim != 3:\n            return {'filename': os.path.basename(filepath), 'error': f\"Not a 3D volume, shape: {vol.shape}\"}\n\n        # 2. Downsample (Optional)\n        # Slicing [::2, ::2, ::2] is the fastest way to downsample\n        if DOWNSAMPLE_RATE > 1:\n            vol = vol[::DOWNSAMPLE_RATE, ::DOWNSAMPLE_RATE, ::DOWNSAMPLE_RATE]\n\n        # 3. Create Binary Mask (1=Sheet)\n        mask = (vol == 1) # Strict check for 1\n        # If your data is 0 and 255, change to: mask = (vol > 0)\n        \n        if not np.any(mask):\n            return None\n\n        # 4. 3D Euclidean Distance Transform (Scipy)\n        # Calculates distance from center to nearest 0 (background) in 3D space\n        dt = distance_transform_edt(mask)\n\n        # 5. 3D Skeletonization\n        # Reduces the sheet to a \"Medial Surface\" or \"Medial Axis\"\n        skel = skeletonize(mask)\n        \n        # 6. Extract Thickness\n        # dt gives Radius. Thickness = 2 * Radius.\n        # We multiply by DOWNSAMPLE_RATE to correct for the shrinking earlier.\n        thickness_values = 2 * dt[skel] * DOWNSAMPLE_RATE\n        \n        if len(thickness_values) == 0:\n            return None\n\n        return {\n            'filename': os.path.basename(filepath),\n            'mean_thickness': np.mean(thickness_values),\n            'median_thickness': np.median(thickness_values),\n            'max_thickness': np.max(thickness_values),\n            'std_dev': np.std(thickness_values),\n            'voxel_count': len(thickness_values) # Volume of skeleton\n        }\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T14:58:01.491182Z","iopub.execute_input":"2025-12-24T14:58:01.492093Z","iopub.status.idle":"2025-12-24T14:58:01.511814Z","shell.execute_reply.started":"2025-12-24T14:58:01.492054Z","shell.execute_reply":"2025-12-24T14:58:01.510735Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if 1:\n    files = sorted(glob.glob(os.path.join(INPUT_FOLDER, \"*.tif\")))\n    if not files:\n        print(\"No .tif files found.\")\n\n    print(f\"Found {len(files)} 3D volumes.\")\n    print(f\"Processing with {NUM_WORKERS} workers. Downsample Rate: {DOWNSAMPLE_RATE}x\")\n\n    # Parallel Processing\n    results = Parallel(n_jobs=NUM_WORKERS)(\n        delayed(process_3d_volume)(f) for f in tqdm(files, unit=\"vol\")\n    )\n\n    clean_results = [r for r in results if r is not None]\n\n    if not clean_results:\n        print(\"No valid results obtained.\")\n\n    df = pd.DataFrame(clean_results)\n    \n    # Save\n    cols = ['filename', 'mean_thickness', 'median_thickness', 'std_dev', 'voxel_count']\n    if 'error' in df.columns:\n        cols.append('error')\n    \n    df = df.reindex(columns=cols)\n    df.to_csv(OUTPUT_CSV, index=False)\n\n    print(\"\\n--- Summary ---\")\n    if 'mean_thickness' in df.columns:\n        print(df[['mean_thickness', 'median_thickness']].describe().to_markdown())\n    else:\n        print(df.head().to_markdown())\n        \n    print(f\"\\nSaved to {os.path.abspath(OUTPUT_CSV)}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T14:58:01.513043Z","iopub.execute_input":"2025-12-24T14:58:01.513580Z"}},"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},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}