{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.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":61446,"databundleVersionId":6962461,"sourceType":"competition"},{"sourceId":7538707,"sourceType":"datasetVersion","datasetId":4389862},{"sourceId":7554261,"sourceType":"datasetVersion","datasetId":4399768},{"sourceId":7574687,"sourceType":"datasetVersion","datasetId":4410212},{"sourceId":150248402,"sourceType":"kernelVersion"}],"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# For submission. Make sure you load the correct Unet and MLP models\n\nHaving serious problems with RAM. Each prediction in float16 format can take huge space.\n\nKidney 1 volume has (2279, 1303, 912) shape.\n\nMaking 3 predictions would mean creating 3x(2279, 1303, 912) in float16 format, so that they can be parsed through the MLP classifier.\n\nNeither there is enough RAM (30gb) or enough VRAM (15Gb each)\n\nPotential solution is to save each prediction to disk (limited to 70 Gb?) and then use dask to load blocks and then process each block\n\nDask storage works\n","metadata":{}},{"cell_type":"markdown","source":"Running MLP on blocks of 512x512x512. MLP is quite slow.\n\nThis new version uses an approximation of the MLP interpolated using scipy RectangularGridInterpolator. It is much faster.\n\nAdds multiple rotation predictions for each slice","metadata":{}},{"cell_type":"code","source":"# Imports\nimport numpy as np\nfrom pathlib import Path\nimport matplotlib.pyplot as plt\nimport tifffile\nimport h5py # maybe dont need this\nimport pandas as pd\nfrom pathlib import Path\nfrom PIL import Image\nfrom torch.utils.data import Dataset, DataLoader, random_split, Subset, TensorDataset\nimport torch\nimport torch.nn as nn\nimport albumentations as alb\nimport albumentations.pytorch\nimport cv2\nfrom tqdm import tqdm\nimport datetime\nimport gc\nimport shutil\nimport os\nfrom torch.nn.parallel import DataParallel\nimport dask.array as da\nimport dask\nfrom glob import glob\nimport pickle","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:11.057129Z","iopub.execute_input":"2024-02-06T20:16:11.057447Z","iopub.status.idle":"2024-02-06T20:16:11.069349Z","shell.execute_reply.started":"2024-02-06T20:16:11.057420Z","shell.execute_reply":"2024-02-06T20:16:11.068119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from scipy.interpolate import RegularGridInterpolator","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:11.072395Z","iopub.execute_input":"2024-02-06T20:16:11.072718Z","iopub.status.idle":"2024-02-06T20:16:11.080161Z","shell.execute_reply.started":"2024-02-06T20:16:11.072691Z","shell.execute_reply":"2024-02-06T20:16:11.079179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Extra installations for segmentation_models_pytorch","metadata":{}},{"cell_type":"code","source":"!python -m pip install --no-index --find-links=/kaggle/input/pip-download-for-segmentation-models-pytorch segmentation-models-pytorch -q","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:11.081269Z","iopub.execute_input":"2024-02-06T20:16:11.081576Z","iopub.status.idle":"2024-02-06T20:16:32.423738Z","shell.execute_reply.started":"2024-02-06T20:16:11.081540Z","shell.execute_reply":"2024-02-06T20:16:32.422292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import segmentation_models_pytorch as smp","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:32.425387Z","iopub.execute_input":"2024-02-06T20:16:32.425744Z","iopub.status.idle":"2024-02-06T20:16:35.588556Z","shell.execute_reply.started":"2024-02-06T20:16:32.425710Z","shell.execute_reply":"2024-02-06T20:16:35.587442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from dotenv import load_dotenv\n# load_dotenv()","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:35.590088Z","iopub.execute_input":"2024-02-06T20:16:35.590515Z","iopub.status.idle":"2024-02-06T20:16:35.595770Z","shell.execute_reply.started":"2024-02-06T20:16:35.590480Z","shell.execute_reply":"2024-02-06T20:16:35.594365Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Configurations","metadata":{}},{"cell_type":"code","source":"#FASTAI_MODEL_FN = \"/kaggle/input/2024-01-08-fastai-mlp/multiaxis_models/2024-01-08_kidney_multiaxis_fastai_corr_meanstd_sigma_2.5_resnet50.dpkl\" \n#it says resnet50 but it is really resenet34\n\n#NN1_MODEL_FN = \"/kaggle/input/2024-01-08-fastai-mlp/multiaxis_models/2024-01-08_kidney_multiaxis_fastai_corr_meanstd_sigma_2.5_resnet50.dpkl\"\n\n#file says is MANet but it is fact a Unet (bug in training code)\n#arch, encoder, model_fn = \"Unet\",\"se_resnext50_32x4d\", \"/kaggle/input/pytorch-models-2024-01-31/2024-01-31_MANet_se_resnext50_32x4d_ep30_01_BCE_DiceS.pth\"\n\n\n# arch, encoder, model_fn = \"Unet\",\"resnet\", \"/kaggle/input/2024-01-30-unet-resnet34-ep30-01-bce-dices/2024-01-30_Unet_resnet34_ep30_01_BCE_DiceS.pth\"\n# #MLP_MODEL_FN = \"/kaggle/input/2024-01-30-unet-resnet34-ep30-01-bce-dices/2024-01-30_Unet_resnet34_ep30_01_BCE_DiceS_3axis_MLP3551sigm.pth\"\n# MLP_INTERP_PKL_FN=\"/kaggle/input/2024-01-30-unet-resnet34-ep30-01-bce-dices/2024-01-30_Unet_resnet34_ep30_01_BCE_DiceS_3axis_MLP3551sigm_RegInterp.pkl\"\n\narch, encoder, model_fn = \"Unet\",\"resnet50\", \"/kaggle/input/2024-02-06-unet-resnet50-ep10-02-bce-sdice-gnoise/2024-02-06_Unet_resnet50_ep10_02_BCE_SDice_Gnoise.pth\"\n#MLP_MODEL_FN = \"/kaggle/input/2024-01-30-unet-resnet34-ep30-01-bce-dices/2024-01-30_Unet_resnet34_ep30_01_BCE_DiceS_3axis_MLP3551sigm.pth\"\nMLP_INTERP_PKL_FN=\"/kaggle/input/2024-02-06-unet-resnet50-ep10-02-bce-sdice-gnoise/2024-02-06_Unet_resnet50_ep10_02_BCE_SDice_Gnoise_RegInterp.pkl\"","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:38.121663Z","iopub.execute_input":"2024-02-06T20:16:38.122036Z","iopub.status.idle":"2024-02-06T20:16:38.128690Z","shell.execute_reply.started":"2024-02-06T20:16:38.122007Z","shell.execute_reply":"2024-02-06T20:16:38.127322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CFG_IMGSIZE=512 # for NN 2D inference\nCFG_MLP_BLOCKSIZE=384 #Keep low, to reduce RAM footprint\n\n#DEVICE= \"cuda:0\"\nDEVICE= \"cuda\"\n\n#NN2_THR=0.5 # Sets the threshold to create boolean mask from the MLP NN2 inference\n#NN2_THR=0.4\n#NN2_THR=0.6\n\n#added stride for predictions in 2D.\n#Predicitons are 512x512, and stride jumps.\n# First versions had stride 512-64 = 448, maybe too small\n#IMG_2D_PRED_STRIDE=496\n\n# NN2_THR=0.4\n# IMG_2D_PRED_STRIDE=384 # should give 2xpad = 128 , 384 crashes with out of memory\n\n# NN2_THR=0.5\n# IMG_2D_PRED_STRIDE=440\n\n#To run\nNN2_THR=0.45\nIMG_2D_PRED_STRIDE=440 ","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:38.828383Z","iopub.execute_input":"2024-02-06T20:16:38.828822Z","iopub.status.idle":"2024-02-06T20:16:38.834649Z","shell.execute_reply.started":"2024-02-06T20:16:38.828779Z","shell.execute_reply":"2024-02-06T20:16:38.833511Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DEBUG=False\n# Make it false before submitting\n# When DEBUG=True The data generated will be limited to 256x256x256 and composed onf random ints with values 20-1000\n\nOVERRIDE_TEST_WITH_TRAIN1DENSE=False\n#Override for test run purposes, no surface dice score calculated\nCROP_512_TRAIN1DENSE=False\n\n#block_size = (512,512,512)\n#if DEBUG:\n#    block_size = (200,200,200)\n\nis_submit = len(glob(\"/kaggle/input/blood-vessel-segmentation/test/kidney_5/images/*.tif\")) != 3\nif is_submit:\n    DEBUG=False\n    OVERRIDE_TEST_WITH_TRAIN1DENSE=False\n    CROP_512_TRAIN1DENSE=False","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:39.098347Z","iopub.execute_input":"2024-02-06T20:16:39.099089Z","iopub.status.idle":"2024-02-06T20:16:39.110040Z","shell.execute_reply.started":"2024-02-06T20:16:39.099054Z","shell.execute_reply":"2024-02-06T20:16:39.109047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"is_submit:\",is_submit)","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:39.279211Z","iopub.execute_input":"2024-02-06T20:16:39.279612Z","iopub.status.idle":"2024-02-06T20:16:39.285041Z","shell.execute_reply.started":"2024-02-06T20:16:39.279580Z","shell.execute_reply":"2024-02-06T20:16:39.284047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Temp file for data vol, to save RAM. This code Defines file and cleans up","metadata":{}},{"cell_type":"code","source":"TEMP_VOL_FILE = \"vol.h5\"\n\ndef delete_h5_temp_file():\n    # If file exists, delete it.\n    if os.path.isfile(TEMP_VOL_FILE):\n        os.remove(TEMP_VOL_FILE)\n\ndelete_h5_temp_file()\n\ndef delete_all_h5_files():\n    for f in glob(\"*.h5\"):\n        os.remove(f)\n\ndelete_all_h5_files()","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:39.619253Z","iopub.execute_input":"2024-02-06T20:16:39.619648Z","iopub.status.idle":"2024-02-06T20:16:39.626312Z","shell.execute_reply.started":"2024-02-06T20:16:39.619617Z","shell.execute_reply":"2024-02-06T20:16:39.625298Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Code utilities","metadata":{}},{"cell_type":"code","source":"def normalize_by_mean_std_with_clip(image, **kwargs):\n    #Clips data to mean-sigma*std and mean+sigma*std\n    # Data is not really clipped. Data outside is just made much less varying\n    sigma=3.0\n    smooth=1e-9\n\n    mean=np.mean(image)\n    std=np.std(image)\n    clipv=sigma*std\n\n    x= (image-mean)/(clipv+smooth)\n    data0 = (np.clip(x, -1.0, 1.0)+1.0)/2.0\n    return data0 #values between 0 and +1\n\ndef normalize_by_mean_std_with_clip35(image, **kwargs):\n    #Clips data to mean-sigma*std and mean+sigma*std\n    # Data is not really clipped. Data outside is just made much less varying\n    smooth=1e-10\n\n    mean=np.mean(image)\n    std=np.std(image)\n    clipv=8.0*std #8.0 = 3.0+5.0\n\n    x= (image-mean)/(clipv+smooth)\n    data0 = (np.clip(x, -3.0, 5.0)+3.0)/8.0\n    return data0 #values between 0 and +1\n\ndef get_train_tfm(img_shape):\n    assert len(img_shape)==2\n    #Cuts the largest centre square and then applies augmentation transforms\n    first_crop_shape=[ int(i*1.4) for i in img_shape]\n\n    tfm = alb.Compose([\n        alb.ToFloat(max_value=32767.0),\n        alb.RandomCrop(*first_crop_shape, always_apply=True),\n        #alb.Resize(512,512),\n        alb.RandomRotate90(p=1.0),\n        alb.RandomScale(scale_limit=(0.8,1.25),interpolation=cv2.INTER_CUBIC,p=0.05),\n        alb.Rotate(limit=40, p= 0.5),\n        alb.HorizontalFlip(p=0.5),\n        alb.CenterCrop(*img_shape, always_apply=True),\n        #alb.Lambda(name=\"normalize_by_mean_std_with_clip35\", image=normalize_by_mean_std_with_clip35, always_apply=True),\n        alb.Lambda(name=\"normalize_by_mean_std_with_clip\", image=normalize_by_mean_std_with_clip, always_apply=True),\n        \n        alb.RandomGamma(p=0.03),\n        alb.RandomBrightnessContrast(p=0.6),\n        alb.GaussianBlur(p=0.05),\n        alb.MotionBlur(p=0.05),\n        alb.GridDistortion(num_steps=5, distort_limit=0.3, p=0.05),\n        albumentations.pytorch.ToTensorV2()\n    ])\n    return tfm\n\ndef get_prepreds_tfms_from_uint16(img_shape):\n    \"\"\"\n    Transforms to prepare data for running predictions\n    \"\"\"\n\n    tfm = alb.Compose([\n        alb.ToFloat(max_value=65535.0),\n        #alb.CenterCrop(*img_shape,always_apply=True),\n        alb.Lambda(name=\"normalize_by_mean_std_with_clip\", image=normalize_by_mean_std_with_clip, always_apply=True),\n        albumentations.pytorch.ToTensorV2()\n    ])\n    return tfm\n\ndef get_prepreds_tfms_from_int16(img_shape):\n    \"\"\"\n    Transforms to prepare data for running predictions\n    Assumes image has the right shape 512x512\n    \"\"\"\n\n    tfm = alb.Compose([\n        alb.ToFloat(max_value=32765.0),\n        #alb.CenterCrop(*img_shape,always_apply=True),\n        alb.Lambda(name=\"normalize_by_mean_std_with_clip\", image=normalize_by_mean_std_with_clip, always_apply=True),\n        albumentations.pytorch.ToTensorV2()\n    ])\n    return tfm\n\ndef get_post_pred_tfms(orig_size):\n    \"\"\"\n    Params:\n        orig_size: tuple (height, width) of the original image. Image and mask will\n        be resized to this size.\n    \"\"\"\n    tfm = alb.Compose([\n        alb.Resize(*orig_size)\n    ])","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:39.947252Z","iopub.execute_input":"2024-02-06T20:16:39.947660Z","iopub.status.idle":"2024-02-06T20:16:39.965779Z","shell.execute_reply.started":"2024-02-06T20:16:39.947628Z","shell.execute_reply":"2024-02-06T20:16:39.964466Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Cleanup","metadata":{}},{"cell_type":"markdown","source":"# Get samples names and locations","metadata":{}},{"cell_type":"code","source":"list(Path(\"/kaggle/input/blood-vessel-segmentation/test\").iterdir())","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:40.463060Z","iopub.execute_input":"2024-02-06T20:16:40.463555Z","iopub.status.idle":"2024-02-06T20:16:40.476142Z","shell.execute_reply.started":"2024-02-06T20:16:40.463517Z","shell.execute_reply":"2024-02-06T20:16:40.475036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"samples =[]\n\nfor dir0 in Path(\"/kaggle/input/blood-vessel-segmentation/test\").iterdir():\n    print(\"dir0:\",dir0)\n    sample_name = dir0.parts[-1]\n    print(\"sample_name:\",sample_name)\n    samples.append({\"sample_path_dir\": dir0, \"sample_name\":sample_name})","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:40.639465Z","iopub.execute_input":"2024-02-06T20:16:40.639863Z","iopub.status.idle":"2024-02-06T20:16:40.647173Z","shell.execute_reply.started":"2024-02-06T20:16:40.639822Z","shell.execute_reply":"2024-02-06T20:16:40.645937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# For testing purposes to see if the code can run with a large volume\n# use kidney_1_dense dataset\nif OVERRIDE_TEST_WITH_TRAIN1DENSE:\n    samples=[ {'sample_path_dir': Path('/kaggle/input/blood-vessel-segmentation/train/kidney_1_dense'),\n                'sample_name': 'kidney_1'}]\n    ","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:40.815490Z","iopub.execute_input":"2024-02-06T20:16:40.815858Z","iopub.status.idle":"2024-02-06T20:16:40.821267Z","shell.execute_reply.started":"2024-02-06T20:16:40.815829Z","shell.execute_reply":"2024-02-06T20:16:40.820050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"samples","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:40.980955Z","iopub.execute_input":"2024-02-06T20:16:40.981357Z","iopub.status.idle":"2024-02-06T20:16:40.987755Z","shell.execute_reply.started":"2024-02-06T20:16:40.981328Z","shell.execute_reply":"2024-02-06T20:16:40.986757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Setup and load model(s)","metadata":{}},{"cell_type":"markdown","source":"NN1","metadata":{}},{"cell_type":"code","source":"def load_model(arch, enc, dict_fn, weights=None):\n    model0=None\n    if arch.lower()==\"unet\":\n        model0=smp.Unet(encoder_name=enc, encoder_weights=weights ,in_channels=1, classes=1, activation=\"sigmoid\")\n    elif arch.lower()==\"manet\":\n        model0=smp.MAnet(encoder_name=enc, encoder_weights=weights ,in_channels=1, classes=1, activation=\"sigmoid\")\n    else:\n        raise ValueError(f\"arch:{arch} not valid.\")\n    \n    model0.load_state_dict(torch.load(dict_fn))\n    \n    model0.to(DEVICE)\n    model0.eval()\n\n    return model0","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:41.443758Z","iopub.execute_input":"2024-02-06T20:16:41.444169Z","iopub.status.idle":"2024-02-06T20:16:41.454673Z","shell.execute_reply.started":"2024-02-06T20:16:41.444136Z","shell.execute_reply":"2024-02-06T20:16:41.451762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model0= load_model(arch,encoder,model_fn)","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:41.630030Z","iopub.execute_input":"2024-02-06T20:16:41.630404Z","iopub.status.idle":"2024-02-06T20:16:44.038641Z","shell.execute_reply.started":"2024-02-06T20:16:41.630377Z","shell.execute_reply":"2024-02-06T20:16:44.037176Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model0=DataParallel(model0)","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.040642Z","iopub.execute_input":"2024-02-06T20:16:44.041125Z","iopub.status.idle":"2024-02-06T20:16:44.046041Z","shell.execute_reply.started":"2024-02-06T20:16:44.041082Z","shell.execute_reply":"2024-02-06T20:16:44.045034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"NN2","metadata":{}},{"cell_type":"code","source":"class MLPClassifier_3_5_5_1_sigm(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.fc1 = nn.Linear(3, 5)\n        self.fc2 = nn.Linear(5, 5)\n        self.fc3 = nn.Linear(5, 1)\n        self.tanh = nn.Tanh()\n        self.sigm = nn.Sigmoid()\n        \n\n    def forward(self, x):\n        x = self.tanh(self.fc1(x))\n        x = self.tanh(self.fc2(x))\n        x = self.fc3(x)\n        x = self.sigm(x) #use BCELoss, not BCELossWithLogits\n        return x","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.047436Z","iopub.execute_input":"2024-02-06T20:16:44.047718Z","iopub.status.idle":"2024-02-06T20:16:44.069431Z","shell.execute_reply.started":"2024-02-06T20:16:44.047694Z","shell.execute_reply":"2024-02-06T20:16:44.068394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model_MLP_fusion = MLPClassifier_3_5_5_1_sigm()\n# model_MLP_fusion.load_state_dict(torch.load(MLP_MODEL_FN))\n# model_MLP_fusion.to(DEVICE)\n# model_MLP_fusion.eval()","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.072448Z","iopub.execute_input":"2024-02-06T20:16:44.073172Z","iopub.status.idle":"2024-02-06T20:16:44.077913Z","shell.execute_reply.started":"2024-02-06T20:16:44.073141Z","shell.execute_reply":"2024-02-06T20:16:44.076854Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# str(next(model_MLP_fusion.parameters()).device)","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.079107Z","iopub.execute_input":"2024-02-06T20:16:44.079404Z","iopub.status.idle":"2024-02-06T20:16:44.086267Z","shell.execute_reply.started":"2024-02-06T20:16:44.079379Z","shell.execute_reply":"2024-02-06T20:16:44.085053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"CPU is marginally better","metadata":{}},{"cell_type":"code","source":"# model_MLP_fusion.cpu()","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.087465Z","iopub.execute_input":"2024-02-06T20:16:44.087776Z","iopub.status.idle":"2024-02-06T20:16:44.093746Z","shell.execute_reply.started":"2024-02-06T20:16:44.087739Z","shell.execute_reply":"2024-02-06T20:16:44.092597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load MLP Interpolator","metadata":{}},{"cell_type":"code","source":"# from scipy.interpolate import RegularGridInterpolator, LinearNDInterpolator, NearestNDInterpolator","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.094892Z","iopub.execute_input":"2024-02-06T20:16:44.095231Z","iopub.status.idle":"2024-02-06T20:16:44.102422Z","shell.execute_reply.started":"2024-02-06T20:16:44.095204Z","shell.execute_reply":"2024-02-06T20:16:44.101410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open(MLP_INTERP_PKL_FN, 'rb') as f:\n    MLP_interp_model = pickle.load(f) # RegularGridInterpolator","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.103782Z","iopub.execute_input":"2024-02-06T20:16:44.104173Z","iopub.status.idle":"2024-02-06T20:16:44.114489Z","shell.execute_reply.started":"2024-02-06T20:16:44.104137Z","shell.execute_reply":"2024-02-06T20:16:44.113535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MLP_interp_model","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.115757Z","iopub.execute_input":"2024-02-06T20:16:44.116104Z","iopub.status.idle":"2024-02-06T20:16:44.122631Z","shell.execute_reply.started":"2024-02-06T20:16:44.116078Z","shell.execute_reply":"2024-02-06T20:16:44.121491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Setup functions","metadata":{}},{"cell_type":"markdown","source":"## function to collect volume from path dir","metadata":{}},{"cell_type":"code","source":"# Note that DEBUG will override data collection\ndef get_data_vol_from_path_dir(path_dir): \n    global DEBUG\n    # Get list of files\n    # Create numpy data object to hold the data from the files\n    if DEBUG:\n        data=np.random.randint(200,1000, size=(256,256,256), dtype=np.uint16)\n        return data\n        \n    imgdata_list = []\n\n    img_fns = sorted(list((path_dir/\"images\").glob(\"*.tif\")))\n\n    for f0 in img_fns:\n        imgdata_list.append( tifffile.imread(f0))\n\n    data=np.array(imgdata_list)\n    \n    return data","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.175789Z","iopub.execute_input":"2024-02-06T20:16:44.176470Z","iopub.status.idle":"2024-02-06T20:16:44.183631Z","shell.execute_reply.started":"2024-02-06T20:16:44.176437Z","shell.execute_reply":"2024-02-06T20:16:44.182491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Note that DEBUG will override data collection\n\ndef get_data_vol_from_path_dir_dask(path_dir):\n    global DEBUG\n    global TEMP_VOL_FILE\n    \n    print(f\"Getting data from folder {path_dir}\")\n    \n    # Get list of files\n    # Create numpy data object to hold the data from the files\n    data=None\n    if DEBUG:\n        data=np.random.randint(200,1000, size=(256,256,256), dtype=np.uint16)\n    else:    \n        imgdata_list = []\n        img_fns = sorted(list((path_dir/\"images\").glob(\"*.tif\")))\n        for f0 in img_fns:\n            imgdata_list.append( tifffile.imread(f0))\n        data=np.array(imgdata_list)\n    \n    with h5py.File(TEMP_VOL_FILE,'w') as h5f:\n        h5f['data']=data\n    \n    del(data) # clear RAM\n    \n    h5fileobj = h5py.File(TEMP_VOL_FILE)\n    data_da=da.from_array(h5fileobj['data']) #dask will do the reading\n        \n    return data_da, h5fileobj #return fileobj so that it can be closed manually","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.381871Z","iopub.execute_input":"2024-02-06T20:16:44.383036Z","iopub.status.idle":"2024-02-06T20:16:44.392054Z","shell.execute_reply.started":"2024-02-06T20:16:44.382972Z","shell.execute_reply":"2024-02-06T20:16:44.390837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Note that DEBUG will override data collection\n# This version gets the ordered list of filenames\ndef get_data_vol_from_path_dir_dask_stems(path_dir):\n    global DEBUG\n    global TEMP_VOL_FILE\n    \n    stems=None\n    \n    print(f\"Getting data from folder {path_dir}\")\n    \n    # Get list of files\n    # Create numpy data object to hold the data from the files\n    data=None\n    if DEBUG:\n        data=np.random.randint(200,1000, size=(256,256,256), dtype=np.uint16)\n        stems = [f\"{iz:04d}\" for iz in range(0,255)]\n    else:\n        imgdata_list = []\n        img_fns = sorted(list((path_dir/\"images\").glob(\"*.tif\")))\n        for f0 in img_fns:\n            imgdata_list.append( tifffile.imread(f0))\n        data=np.array(imgdata_list)\n        \n        stems = [fn0.stem for fn0 in img_fns]\n    \n    with h5py.File(TEMP_VOL_FILE,'w') as h5f:\n        h5f['data']=data\n    \n    del(data) # clear RAM\n    \n    h5fileobj = h5py.File(TEMP_VOL_FILE)\n    data_da=da.from_array(h5fileobj['data']) #dask will do the reading\n    \n    return data_da, h5fileobj, stems #return fileobj so that it can be closed manually\n    # Get also the filename stems so that tehy can be used to write to submission.csv\n    # This is important as test secret filenames may not start at 0000\n","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.534471Z","iopub.execute_input":"2024-02-06T20:16:44.534859Z","iopub.status.idle":"2024-02-06T20:16:44.545332Z","shell.execute_reply.started":"2024-02-06T20:16:44.534828Z","shell.execute_reply":"2024-02-06T20:16:44.544261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Note that DEBUG will override data collection\n# This version gets the ordered list of filenames\ndef get_data_vol_from_path_dir_stems(path_dir):\n    global DEBUG\n    \n    stems=None\n    \n    print(f\"Getting data from folder {path_dir}\")\n    \n    # Get list of files\n    # Create numpy data object to hold the data from the files\n    data=None\n    if DEBUG:\n        data=np.random.randint(200,1000, size=(256,256,256), dtype=np.uint16)\n        stems = [f\"{iz:04d}\" for iz in range(0,255)]\n    else:\n        imgdata_list = []\n        img_fns = sorted(list((path_dir/\"images\").glob(\"*.tif\")))\n        for f0 in img_fns:\n            imgdata_list.append( tifffile.imread(f0))\n        data=np.array(imgdata_list)\n        \n        stems = [fn0.stem for fn0 in img_fns]\n    \n    return data, stems #return fileobj so that it can be closed manually\n    # Get also the filename stems so that tehy can be used to write to submission.csv\n    # This is important as test secret filenames may not start at 0000","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:44.704321Z","iopub.execute_input":"2024-02-06T20:16:44.705132Z","iopub.status.idle":"2024-02-06T20:16:44.713103Z","shell.execute_reply.started":"2024-02-06T20:16:44.705100Z","shell.execute_reply":"2024-02-06T20:16:44.711914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"OK","metadata":{}},{"cell_type":"markdown","source":"## rle encode / decode","metadata":{}},{"cell_type":"code","source":"# Run-Length Encode and Decode\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport time\n\n# ref.: https://www.kaggle.com/stainsby/fast-tested-rle\ndef rle_encode(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\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)\n \ndef rle_decode(mask_rle, shape):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n\n    '''\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape)\n\n#Alternative where mask_rle is a list of values (in string)\ndef rle_decode1(mask_rle, shape):\n    '''\n    mask_rle: run-length as list with values in string format (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n\n    '''\n    #s = mask_rle.split()\n    s= mask_rle\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape)","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:45.198076Z","iopub.execute_input":"2024-02-06T20:16:45.198554Z","iopub.status.idle":"2024-02-06T20:16:45.212215Z","shell.execute_reply.started":"2024-02-06T20:16:45.198524Z","shell.execute_reply":"2024-02-06T20:16:45.211011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_tfm = get_prepreds_tfms_from_uint16((CFG_IMGSIZE,CFG_IMGSIZE))","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:45.374301Z","iopub.execute_input":"2024-02-06T20:16:45.375304Z","iopub.status.idle":"2024-02-06T20:16:45.380083Z","shell.execute_reply.started":"2024-02-06T20:16:45.375271Z","shell.execute_reply":"2024-02-06T20:16:45.378967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"90 degree rotations for 2D predictions\n\nAfter sigmoid, average all results\n\nI am getting out of memory errors\n\n<div class=\"alert alert-block alert-info\">\n<b>Note:</b> CRASHING.</div>","metadata":{}},{"cell_type":"code","source":"def get_prediction_from_2D_image_4rots(data_tfm_2d, model):\n    \"\"\"\n    Runs predictions with 4 different rotations and averages them\n    \"\"\"\n    preds_sum=None\n    to_preds=[]\n    for i in range(4):\n        if i==0:\n            to_pred=data_tfm_2d\n        else:\n            to_pred=torch.rot90(data_tfm_2d,k=i)\n\n        to_preds.append(torch.unsqueeze(to_pred,dim=0))\n\n    batch_to_preds = torch.stack(to_preds, dim=0)\n    #print(f\"batch_to_preds.shape:{batch_to_preds.shape}\")\n\n    pred_batch = model.forward(batch_to_preds)\n    #print(f\"pred_batch.shape:{pred_batch.shape}\")\n\n    #Unstack and unrotate\n\n    for i in range(4):\n        pred_rot = torch.squeeze(pred_batch[i,...])\n        #unrotate\n        if i==0:\n            # pred_unrot=pred\n            preds_sum=pred_rot\n        else:\n            pred_unrot=torch.rot90(pred_rot,k=-i)\n            preds_sum+=pred_unrot\n\n    #Get the average over the 4 rotations\n    preds_rot_mean=preds_sum/4\n    \n    return preds_rot_mean","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:45.725175Z","iopub.execute_input":"2024-02-06T20:16:45.725579Z","iopub.status.idle":"2024-02-06T20:16:45.735927Z","shell.execute_reply.started":"2024-02-06T20:16:45.725548Z","shell.execute_reply":"2024-02-06T20:16:45.734656Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_prediction_from_img_uint16( datai_np, model, stride=CFG_IMGSIZE-64):\n\n    #Split image in overlapping regions\n\n    #Pad if image is smaller than CFG_IMGSIZE in any direction\n\n    orig_shape = datai_np.shape\n    pady=0\n    padx=0\n    if datai_np.shape[0]<CFG_IMGSIZE:\n        #pad along yy\n        pady = CFG_IMGSIZE-datai_np.shape[0]\n    if datai_np.shape[1]<CFG_IMGSIZE:\n        padx = CFG_IMGSIZE-datai_np.shape[1]\n    \n    if pady>0 or padx>0:\n        datai_np = np.pad( datai_np, ((0,pady),(0,padx)) , mode=\"symmetric\")\n    elif pady>0 and padx<=0:\n        datai_np = np.pad( datai_np, ((0,pady),(0,0)) , mode=\"symmetric\")\n    elif pady<=0 and padx>0:\n        datai_np = np.pad( datai_np, ((0,0),(0,padx)) , mode=\"symmetric\")\n    \n    #print(\"orig_shape:\", orig_shape, \"  datai_np.shape:\",datai_np.shape)\n\n    #orgins\n    y0s = list(range(0, datai_np.shape[0]-CFG_IMGSIZE, stride))\n    y0s.append(datai_np.shape[0]-CFG_IMGSIZE)\n    x0s = list(range(0, datai_np.shape[1]-CFG_IMGSIZE, stride))\n    x0s.append(datai_np.shape[1]-CFG_IMGSIZE)\n\n    #print(f\"len(y0s):{len(y0s)} , len(x0s):{len(x0s)}\")\n\n    data_vol_sum_probs=torch.zeros( datai_np.shape, dtype=torch.float16, device=DEVICE)\n    data_vol_sum_occur=torch.zeros( datai_np.shape, dtype=torch.int16, device=DEVICE) #counts occurences for averaging later\n    \n    model.eval()\n\n    for y0 in y0s:\n        y_length=CFG_IMGSIZE\n        if y0<0:\n            #can be negative if imagesize is lower than CFG_IMGSIZE\n            y0=0\n            y_length=datai_np.shape[0]\n        for x0 in x0s:\n            x_length=CFG_IMGSIZE\n            if x0<0:\n                x0=0\n                x_length=datai_np.shape[1]\n                \n            #print(f\"datai_npregion: {y0}:{y0+y_length},{x0}:{x0+x_length}\")\n\n            data0 = datai_np[y0:y0+y_length, x0:x0+x_length]\n            \n            #Apply test_tfms\n            #data_tfm= torch.unsqueeze(test_tfm(image=data0)['image'],dim=0).to(device=DEVICE)\n            \n            #Run predicton\n            #data_test_pred_tensor = model(data_tfm) #result is sigmoid activated\n            #data_vol_sum_probs[y0:y0+CFG_IMGSIZE, x0:x0+CFG_IMGSIZE] += data_test_pred_tensor[0,0,:,:]\n            \n#             print(f\"data_tfm.shape: {data_tfm.shape}\")\n            \n#             preds_rots = []\n#             for i in range(4):\n#                 if i==0:\n#                     preds_rots.append( model(data_tfm)[0,0,:,:] )\n#                 else:\n#                     preds_rots.append( model(torch.rot90(data_tfm, k=i, dims=(-2,-1)))[0,0,:,:] )\n            \n            #Unrotate\n#             print(f\"len(preds_rots):{len(preds_rots)}\")\n#             preds_unrot=[ torch.rot90(preds_rots[i], k=-i )  for i in range(4)] \n#             preds_unrot_stack=torch.stack(preds_unrot, dim=0)\n#             print(f\"preds_unrot_stack.shape:{preds_unrot_stack.shape}\")\n            \n#             data_test_pred_tensor= preds_unrot_stack.mean(0) #mean probability of all the rotation predictions\n            \n#             data_vol_sum_probs[y0:y0+y_length, x0:x0+x_length]+=data_test_pred_tensor\n#             del(preds_rots)\n#             del(data_test_pred_tensor)\n#             del(preds_unrot)\n#             del(preds_unrot_stack)\n            \n            #data_tfm_2d = torch.squeeze(test_tfm(image=data0)['image'],dim=0).to(device=DEVICE)\n            data_tfm_2d = torch.squeeze(test_tfm(image=data0)['image'],dim=0) #Try\n        \n            preds_rot_mean=get_prediction_from_2D_image_4rots(data_tfm_2d, model)\n            \n            data_vol_sum_probs[y0:y0+y_length, x0:x0+x_length]+=preds_rot_mean\n            data_vol_sum_occur[y0:y0+y_length, x0:x0+x_length] += 1\n            \n            del(data_tfm_2d)\n            \n    gc.collect()\n    torch.cuda.empty_cache()\n        \n    data_test_pred_full_mean = (data_vol_sum_probs/ data_vol_sum_occur).detach().cpu().numpy()\n    #data_test_pred_mask = (data_test_pred_full_mean>=0.5)\n\n    if orig_shape!=data_test_pred_full_mean.shape:\n        #crop\n        data_test_pred_full_mean=data_test_pred_full_mean[\n            :orig_shape[0],\n            :orig_shape[1]\n        ]\n    return data_test_pred_full_mean #note that result is in float16 format\n","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:45.996382Z","iopub.execute_input":"2024-02-06T20:16:45.996859Z","iopub.status.idle":"2024-02-06T20:16:46.023597Z","shell.execute_reply.started":"2024-02-06T20:16:45.996817Z","shell.execute_reply":"2024-02-06T20:16:46.022044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Test\n# test0=get_prediction_from_img_uint16 (np.random.random((512,512)), model=model0) # make sure model0 is already defined (see below)\n# test0.shape\n\n#1303, 912\n# strides 496 ok, 384 not ok, 440 ok\n\ntest0=get_prediction_from_img_uint16 (np.random.random((1303,912)), model=model0, stride=440) # make sure model0 is already defined (see below)\ntest0.shape","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:46.214256Z","iopub.execute_input":"2024-02-06T20:16:46.214961Z","iopub.status.idle":"2024-02-06T20:16:50.975628Z","shell.execute_reply.started":"2024-02-06T20:16:46.214911Z","shell.execute_reply":"2024-02-06T20:16:50.974576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict_vol_alongz(data3d, **kwargs):\n    \n    print(\"predict_vol_alongz(), data3d.shape:\", data3d.shape)\n    nz= data3d.shape[0]\n    \n    data0=None\n    if dask.is_dask_collection(data3d):\n        data0=data3d.compute()\n    else:\n        data0=data3d\n        \n    pred_probs_slices=[]\n    for iz in tqdm(range(nz)):\n        slice = data0[iz,:,:]\n#         if dask.is_dask_collection(slice):\n#             slice=slice.compute()\n        slice_pred = get_prediction_from_img_uint16(slice, **kwargs)\n        pred_probs_slices.append(slice_pred)\n    \n    gc.collect()\n    torch.cuda.empty_cache()\n    \n    pred_probs = np.array(pred_probs_slices)\n\n    return pred_probs\n","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:50.977418Z","iopub.execute_input":"2024-02-06T20:16:50.977769Z","iopub.status.idle":"2024-02-06T20:16:50.985377Z","shell.execute_reply.started":"2024-02-06T20:16:50.977741Z","shell.execute_reply":"2024-02-06T20:16:50.984388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # # Test\n# test0=predict_vol_alongz(np.random.random((3, 1303, 912)), model=model0) # make sure model0 is already defined (see below)\n# test0.shape\n# #(3, 1303, 912)","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:50.986649Z","iopub.execute_input":"2024-02-06T20:16:50.987002Z","iopub.status.idle":"2024-02-06T20:16:50.999537Z","shell.execute_reply.started":"2024-02-06T20:16:50.986956Z","shell.execute_reply":"2024-02-06T20:16:50.998336Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"OK","metadata":{}},{"cell_type":"markdown","source":"# Load data (test)","metadata":{}},{"cell_type":"code","source":"#samples","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.002127Z","iopub.execute_input":"2024-02-06T20:16:51.002483Z","iopub.status.idle":"2024-02-06T20:16:51.009301Z","shell.execute_reply.started":"2024-02-06T20:16:51.002443Z","shell.execute_reply":"2024-02-06T20:16:51.008035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#sname = samples[0]['sample_name']\n#sdir= samples[0]['sample_path_dir'] ","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.010507Z","iopub.execute_input":"2024-02-06T20:16:51.010875Z","iopub.status.idle":"2024-02-06T20:16:51.019515Z","shell.execute_reply.started":"2024-02-06T20:16:51.010847Z","shell.execute_reply":"2024-02-06T20:16:51.018334Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#data0, h5fileobj, stems =get_data_vol_from_path_dir_dask_stems(sdir)","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.020828Z","iopub.execute_input":"2024-02-06T20:16:51.021164Z","iopub.status.idle":"2024-02-06T20:16:51.029373Z","shell.execute_reply.started":"2024-02-06T20:16:51.021135Z","shell.execute_reply":"2024-02-06T20:16:51.028287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#print(data0.dtype)\n#print(data0.shape)\n","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.030930Z","iopub.execute_input":"2024-02-06T20:16:51.031320Z","iopub.status.idle":"2024-02-06T20:16:51.037862Z","shell.execute_reply.started":"2024-02-06T20:16:51.031281Z","shell.execute_reply":"2024-02-06T20:16:51.036894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# More code","metadata":{}},{"cell_type":"code","source":"# def predict_data_multiaxis(data, model_net):\n#     # Predict usng model0\n    \n#     assert data.ndim==3\n    \n#     print(f\"predict_data_multiaxis() , data dtype:{data.dtype} shape:{data.shape}\")\n    \n#     #return None# debug\n    \n# #    if data.dtype==np.uint16:\n# #        print(\"data is np.uint16, converting to torch format\")\n# #        data_tc = torch.from_numpy((data//2).astype(np.int16))\n# #    elif data.dtype==np.int16:\n# #        print(\"data is np.int16, converting to torch format\")\n# #        data_tc = torch.from_numpy(data)\n# #    else:\n# #        print(\"data is {data.dtype}. No conversion\")\n# #        data_tc=data\n    \n# #    preds_multiaxis=[]\n# #    axs = range(3)\n# #    #axs = [1,2,0] #test\n# #    for i in axs: #axis\n# #        data_to_pred_tc = None\n# #        if i==0: #Z\n# #            print(\"predicting along Z\")\n# #            data_to_pred_tc=data_tc\n# #        elif i==1:#Y\n# #            print(\"predicting along Y\")\n# #            data_to_pred_tc = torch.permute(data_tc,dims=(1,2,0))\n# #        elif i==2:#X\n# #            print(\"predicting along X\")\n# #            data_to_pred_tc = torch.permute(data_tc,dims=(2,0,1))\n# #        \n# #        pred0 = predict_vol_alongz(data_to_pred_tc.numpy(), model= model0 )\n#     data0=None\n#     if data.dtype==np.uint16 or data.dtype==da.uint16:\n#         print(\"data is uint16. Dividing by 2\")\n#         data0 = (data//2).astype(np.int16)\n#         del(data)\n#     elif data.dtype==np.int16 or data.dtype==da.int16:\n#         print(\"data is int16, converting to torch format\")\n#         data0 = data\n#     else:\n#         print(\"data is {data.dtype}. No conversion\")\n#         data_tc=data\n        \n#     preds_multiaxis=[]\n#     axs = range(3)\n#     #axs = [1,2,0] #test\n#     for i in axs: #axis\n#         data_to_pred = None\n#         if i==0: #Z\n#             print(\"predicting along Z\")\n#             data_to_pred=data0\n#         elif i==1:#Y\n#             print(\"predicting along Y\")\n#             data_to_pred = np.transpose(data0,axes=(1,2,0))\n#         elif i==2:#X\n#             print(\"predicting along X\")\n#             data_to_pred = np.transpose(data0,axes=(2,0,1))\n        \n#         #pred0 = predict_vol_alongz(data_to_pred, model= model_net ) \n        \n#         #rotate back\n#         if i==1:#Y\n#             pred0 = pred0.transpose( (2,0,1) )\n#         elif i==2:#X\n#             pred0 = pred0.transpose( (1,2,0) )\n        \n#         #Store in cuda:1\n#         pred0_t = torch.from_numpy(pred0).to('cuda:1')\n#         preds_multiaxis_t.append(pred0_t)\n#         preds_multiaxis_t = torch.concatenate(preds_multiaxis_t)\n\n#     return preds_multiaxis_t","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.039462Z","iopub.execute_input":"2024-02-06T20:16:51.039853Z","iopub.status.idle":"2024-02-06T20:16:51.048857Z","shell.execute_reply.started":"2024-02-06T20:16:51.039826Z","shell.execute_reply":"2024-02-06T20:16:51.047833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict_data_multiaxis_to_h5files(data, model_net):\n    \"\"\"\n    Predict and saves result to file,\n    Returns a list with filanames for each prediction\n    \"\"\"\n    \n    assert data.ndim==3\n    \n    print(f\"predict_data_multiaxis_to_h5files() , data dtype:{data.dtype} shape:{data.shape}\")\n    \n    data0=None\n    if data.dtype==np.uint16:\n        print(\"Data is uint16. Dividing by 2\")\n        data0 = (data//2).astype(np.int16)\n        del(data)\n    else:\n        data0 = data\n\n    preds_files_list=[]\n    axs = range(3)\n    #axs = [1,2,0] #test\n    for i in axs: #axis\n        data_to_pred = None\n        if i==0: #Z\n            print(\"predicting along Z\")\n            data_to_pred=data0\n        elif i==1:#Y\n            print(\"predicting along Y\")\n            data_to_pred = np.transpose(data0,axes=(1,2,0))\n        elif i==2:#X\n            print(\"predicting along X\")\n            data_to_pred = np.transpose(data0,axes=(2,0,1))\n        \n        #pred0 = predict_vol_alongz(data_to_pred, model= model_net )\n        pred0 = predict_vol_alongz(data_to_pred, model= model_net, stride=IMG_2D_PRED_STRIDE )\n        \n        #rotate back\n        if i==1:#Y\n            pred0 = pred0.transpose( (2,0,1) )\n        elif i==2:#X\n            pred0 = pred0.transpose( (1,2,0) )\n        \n        #Save\n        fname = f\"pred_{i}.h5\"\n        print(f\"Saving prediction to {fname}\")\n        #with h5py.File(fname, 'w') as f:\n        #    f['data']=pred0\n        #    preds_files_list.append(fname)\n\n        f= h5py.File(fname,'w')\n        #f.create_dataset('data', chunks=(512,512,512), data=pred0, compression='gzip' ) #can throw error if the size is smaller in any direction\n        f.create_dataset('data', data=pred0, compression='gzip' )\n        f.close()\n        \n        preds_files_list.append(fname)\n        \n        del(pred0)\n        gc.collect()\n        \n    return preds_files_list","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.050665Z","iopub.execute_input":"2024-02-06T20:16:51.051014Z","iopub.status.idle":"2024-02-06T20:16:51.065275Z","shell.execute_reply.started":"2024-02-06T20:16:51.050953Z","shell.execute_reply":"2024-02-06T20:16:51.064159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Test\n# IMG_2D_PRED_STRIDE=440 # 496 384\n# test0=predict_data_multiaxis_to_h5files(np.random.random((3, 1303, 912)), model_net=model0) # make sure model0 is already defined (see below)\n# test0.shape\n\n#Crashes out of VRAM","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.068346Z","iopub.execute_input":"2024-02-06T20:16:51.068669Z","iopub.status.idle":"2024-02-06T20:16:51.078771Z","shell.execute_reply.started":"2024-02-06T20:16:51.068633Z","shell.execute_reply":"2024-02-06T20:16:51.077890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # test chnk saving\n# data_test = np.random.random((2279, 1303, 912)).astype(np.float16)\n# f= h5py.File(\"test.h5\",'w')\n# f.create_dataset('data', chunks=(512,512,512), data=data_test, compression='gzip' )\n# f.close()\n\n#OK","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.080243Z","iopub.execute_input":"2024-02-06T20:16:51.080632Z","iopub.status.idle":"2024-02-06T20:16:51.091519Z","shell.execute_reply.started":"2024-02-06T20:16:51.080589Z","shell.execute_reply":"2024-02-06T20:16:51.090176Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def MLP_infer_on_preds(data_multi_preds_probs, mlp_model, batch_size=4096, thresh=0.5, do_parallel=True):\n#     # Expect shape (3, Z,Y,X)\n    \n#     print(\"MLP_infer_on_preds()\")\n#     # ensure data is numpy\n    \n#     mlp_device = next(model_MLP_fusion.parameters()).device\n#     print(f\"mlp_device:{mlp_device}\")\n    \n# #     data_multi_preds_probs_np=None\n# #     if isinstance(data_multi_preds_probs, np.ndarray):\n# #         data_multi_preds_probs_np=data_multi_preds_probs\n# #     elif isinstance(data_multi_preds_probs, torch.Tensor):\n# #         print(\"data is Tensor. Converting to numpy\")\n# #         data_multi_preds_probs_np = data_multi_preds_probs.detach().cpu().numpy()\n\n# #     #data_multi_preds_probs_np = np.array(data_multi_preds_probs)\n# #     s=data_multi_preds_probs_np.shape # keep this, as we will need to reshape result from flat to this shape\n# #     print(\"data_multi_preds_probs_np.shape:\", s)\n# #     print(\"Reshaping to flat\")\n\n# #     p0= data_multi_preds_probs_np.reshape( (s[0], np.prod(s[1:])) )\n# #     data_flat_for_mlp= p0.transpose((1,0))\n    \n# #     #ensure that data is on the same device\n# #     topred_tc= torch.from_numpy(data_flat_for_mlp).float().to(mlp_device)\n\n\n#     data_tc=None\n#     s=data_multi_preds_probs.shape \n#     print(\"data_multi_preds_probs.shape:\", s)\n    \n#     if isinstance(data_multi_preds_probs, np.ndarray):\n#         print(\"Data is numpy. Conversion to torch tensor\")\n#         #data_tc= torch.from_numpy(data_multi_preds_probs).half().to(mlp_device) #half is float16\n#         data_tc= torch.from_numpy(data_multi_preds_probs).float().to(mlp_device) #half is float16\n        \n#     elif isinstance(data_multi_preds_probs, torch.Tensor):\n#         print(\"Data is Tensor. No conversion needed\")\n#         data_tc = data_multi_preds_probs.to(mlp_device)\n\n#     print(\"Reshaping tensor to flat\")\n\n#     p0= data_tc.reshape( (s[0], np.prod(s[1:])) )\n#     #data_flat_for_mlp= p0.transpose((1,0))\n#     topred_tc= torch.permute(p0,(1,0))\n    \n#     print(\"Flatteded data_tc to shape: \",topred_tc.shape)\n#     gc.collect()\n    \n#     #print(topred_tc.device)\n#     data_tc_ds = TensorDataset(topred_tc)\n#     data_tc_batcher = DataLoader(data_tc_ds, batch_size=batch_size, shuffle=False)\n\n#     res_l=[]\n    \n#     mlp_model0 = mlp_model\n#     if do_parallel:\n#         if  \"cuda\" in str(mlp_device):\n#             mlp_model0=DataParallel(mlp_model0)\n#         else:\n#             print(\"Cannot parallelise unless using cuda\")\n        \n#     #mlp_model.to(device)\n#     mlp_model0.eval()\n    \n#     print(\"Beggining NN2 inference of whole volume\")\n#     #with torch.autocast(str(mlp_device))\n#     if \"cuda\" in str(mlp_device):\n#         ac_dev='cuda' #autocast device\n#     else:\n#         ac_dev='cpu'\n        \n#     for data_batch in tqdm(data_tc_batcher):\n#         #print(f\"data_batch[0] device:{data_batch[0].device}\")\n#         data0=data_batch[0]\n           \n#         with torch.autocast(ac_dev):\n#             pred0=mlp_model0(data0)\n            \n#         res= torch.squeeze(pred0)\n#         res_l.append(res>=0.5)\n#         #gc.collect()\n\n#     res = torch.concatenate(res_l)\n\n#     print(\"res.shape:\", res.shape)\n\n#     #r1 = r0>0.5\n#     r2 = res.detach().cpu().numpy().reshape(*s[1:]) #reshape removing the multiaxis dim\n\n#     return r2 #result in numpy and boolean format","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.093463Z","iopub.execute_input":"2024-02-06T20:16:51.093864Z","iopub.status.idle":"2024-02-06T20:16:51.102164Z","shell.execute_reply.started":"2024-02-06T20:16:51.093832Z","shell.execute_reply":"2024-02-06T20:16:51.101262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def MLP_interp_infer_on_preds(data_multi_preds_probs, mlp_interp_model,thresh=0.5,):\n    # Expect shape (3, Z,Y,X)\n    \n    print(\"MLP_interp_infer_on_preds()\")\n    # ensure data is numpy\n    \n    assert data_multi_preds_probs.ndim==4\n\n    d0 = data_multi_preds_probs.transpose(1,2,3,0)\n    \n    r0 = mlp_interp_model(d0)\n    print(f\"MLP interpolation completed. r0.shape:{r0.shape}\")\n    \n    r2_bool = r0>=thresh\n\n    return r2_bool #result in numpy and boolean format","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.103361Z","iopub.execute_input":"2024-02-06T20:16:51.103684Z","iopub.status.idle":"2024-02-06T20:16:51.115222Z","shell.execute_reply.started":"2024-02-06T20:16:51.103649Z","shell.execute_reply":"2024-02-06T20:16:51.114198Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def MLP_preds_on_h5files(f_h5list, **kwargs):\n    \"\"\"\n    Runs MLP across the 3 volumes at each zyx coordinate\n    By default splits volumes in 512x512x512\n    \n    kwargs are arguments passed to MLP_infer_on_preds\n    \"\"\"\n    print(\"MLP_preds_on_h5files()\")\n    \n    pred_all=None\n    \n    h5_file_objs = [ h5py.File(fn, 'r+') for fn in f_h5list ] #get file objects of all files\n    print(f\"h5_file_objs: {h5_file_objs}\")\n    assert len(h5_file_objs)>0\n    \n    gc.collect()\n    \n    S=CFG_MLP_BLOCKSIZE\n    try:\n        \n        #da_objs = [ da.from_array(f0[\"data\"], chunks=(512,512,512)) for f0 in h5_file_objs]\n        da_objs = [ da.from_array(f0[\"data\"], chunks=(S,S,S)) for f0 in h5_file_objs] #it is possible that datasize is smaller than chunk size\n        #it does not throw error\n        \n        #New version that check chunk shape and adjusts to minimum\n#         da_objs=[]\n#         for f0 in h5_file_objs:\n#             obj_data = f0['data']\n#             sh = obj_data.shape\n            \n#             chunkshape = [min(S[i],sh[i]) for i in range(3)]\n            \n#             print(f\"obj_data shape: {obj_data}. Setting chunkshape:{chunkshape}\")\n#             obj_da=da.from_array(obj_data, chunks=chunkshape)\n#             da_objs.append(obj_data)\n\n        print(f\"da_objs: {da_objs}\")\n        assert len(da_objs)>0\n\n        assert da_objs[0].shape==da_objs[1].shape # and so on\n\n        s = da_objs[0].shape\n\n        pred_all = np.zeros(s, dtype=bool)\n\n        for iz in range(0,s[0],S):\n            zend = iz+S\n            if zend>s[0]:\n                zend=s[0]\n            for iy in range(0,s[1],S):\n                yend=iy+S\n                if yend>s[1]:\n                    yend=s[1]\n                for ix in range(0,s[2],S):\n                    xend=ix+S\n                    if xend>s[2]:\n                        xend=s[2]\n                    print(f\"MLP of block [{iz}:{zend},{iy}:{yend},{ix}:{xend}]\")\n                    probs_blocks = [d[iz:zend,iy:yend,ix:xend].compute() for d in da_objs]\n                    probs_blocks_np = np.array(probs_blocks) #stack them\n\n                    print(f\"probs_blocks_np dtype:{probs_blocks_np.dtype} shape:{probs_blocks_np.shape}\")\n\n                    #Run the MLP classification with this block\n                    # pred_block_bool = MLP_infer_on_preds(probs_blocks_np, **kwargs)\n                    # Use the mlp interpolator\n                    pred_block_bool = MLP_interp_infer_on_preds(probs_blocks_np, **kwargs)\n                    \n                    pred_all[iz:zend,iy:yend,ix:xend] = pred_block_bool\n                    \n                    gc.collect()\n    \n    except Exception as e:\n        print(\"ERROR:\")\n        print(e)\n    finally:\n        # files can now be closed\n        print(\"Closing h5 files\")\n        _ = [o.close() for o in h5_file_objs]\n    \n    return pred_all","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.116730Z","iopub.execute_input":"2024-02-06T20:16:51.117077Z","iopub.status.idle":"2024-02-06T20:16:51.132778Z","shell.execute_reply.started":"2024-02-06T20:16:51.117050Z","shell.execute_reply":"2024-02-06T20:16:51.131836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Test it with large array\n#probs_test = torch.zeros((3,2279, 1303, 912), dtype=torch.float16, requires_grad=False, device=\"cuda:1\")","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.134001Z","iopub.execute_input":"2024-02-06T20:16:51.134343Z","iopub.status.idle":"2024-02-06T20:16:51.145350Z","shell.execute_reply.started":"2024-02-06T20:16:51.134317Z","shell.execute_reply":"2024-02-06T20:16:51.144471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#\"cuda\" in str(next(model_MLP_fusion.parameters()).device)","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.399018Z","iopub.execute_input":"2024-02-06T20:16:51.400039Z","iopub.status.idle":"2024-02-06T20:16:51.404623Z","shell.execute_reply.started":"2024-02-06T20:16:51.399999Z","shell.execute_reply":"2024-02-06T20:16:51.403299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Function to run full prediction (NN1+NN2) provided a data volume","metadata":{}},{"cell_type":"code","source":"# def predict_full(datavol):\n#     global learn\n#     global model_MLP_fusion\n#     global mlp_device\n    \n#     #Data can be dask, so convert to numpy\n#     #if dask.is_dask_collection(datavol):\n#     #    datavol=datavol.compute()\n    \n#     #nn1_res = NN1_predict(datavol,learn)\n#     #note that data is contrast corrected and converted to uint8 within NN1_predict\n    \n#     #NN1pred_multiax=predict_data_multiaxis(datavol, model0)\n#     NN1pred_multiax_t =predict_data_multiaxis(datavol, model0)\n    \n#     gc.collect()\n#     #Move back to RAM\n#     NN1pred_multiax = NN1pred_multiax_t.cpu().numpy()\n    \n#     print(\"MLP NN2 predictions\")\n#     k3_NN2_pred = MLP_infer_on_preds(NN1pred_multiax, model_MLP_fusion, 16384) #result is boolean\n\n#     return k3_NN2_pred","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:51.972610Z","iopub.execute_input":"2024-02-06T20:16:51.973047Z","iopub.status.idle":"2024-02-06T20:16:51.979162Z","shell.execute_reply.started":"2024-02-06T20:16:51.973015Z","shell.execute_reply":"2024-02-06T20:16:51.977887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict_full_h5(datavol):\n    #global learn\n    global model_MLP_fusion\n    global model0\n    print(\"predict_full_h5()\")\n    \n    #NN1pred_multiax=predict_data_multiaxis(datavol, model0)\n    NN1pred_multiax_h5f= predict_data_multiaxis_to_h5files(datavol, model0)\n\n    print(\"Completed NN1 prediction\")\n    print(f\"file names of predictions:{NN1pred_multiax_h5f}\")\n    \n    gc.collect()\n    \n    print(\"MLP NN2 predictions starting\")\n    # NN2_pred = MLP_preds_on_h5files(NN1pred_multiax_h5f, mlp_model=model_MLP_fusion, batch_size=16384)\n    #Use the MLPinterpolator\n    # def MLP_interp_infer_on_preds(data_multi_preds_probs, mlp_interp_model,thresh=0.5,)\n    NN2_pred = MLP_preds_on_h5files(NN1pred_multiax_h5f, mlp_interp_model=MLP_interp_model, thresh=NN2_THR)\n    \n    \n    # def MLP_infer_on_preds(data_multi_preds_probs, mlp_model, batch_size=4096, thresh=0.5, do_parallel=True)\n\n    return NN2_pred","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:16:54.278431Z","iopub.execute_input":"2024-02-06T20:16:54.278835Z","iopub.status.idle":"2024-02-06T20:16:54.285999Z","shell.execute_reply.started":"2024-02-06T20:16:54.278804Z","shell.execute_reply":"2024-02-06T20:16:54.284804Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predictions\n\nBig loop","metadata":{}},{"cell_type":"markdown","source":"This version below does not open files as dask but as a numpy\n\nAlso the predictions are saved to h5 files and then uses a blocking algorithm to parse through the MLP","metadata":{}},{"cell_type":"code","source":"pd_ids = []\npd_rles = []\n\npreds_bool=None\ndata0=None\n\nfor sample0 in samples:\n    sname = sample0['sample_name']\n    sdir= sample0['sample_path_dir']  \n                    \n    print(f\"sample {sname} , located in {sdir}\")\n\n    data0, stems =get_data_vol_from_path_dir_stems(sdir)\n    \n    if OVERRIDE_TEST_WITH_TRAIN1DENSE and CROP_512_TRAIN1DENSE:\n        print(\"cropping data to 512x512x512\")\n        data0=data0[:512,:512,:512]\n    \n    gc.collect()\n    torch.cuda.empty_cache()\n    \n    print(\"data0.shape:\", data0.shape)\n\n    print(f\"{sname}: Prediction starting\")\n    #preds_bool = predict_full(data0)\n    preds_bool=predict_full_h5(data0)\n    print(f\"{sname}: Prediction completed\")\n\n    assert preds_bool.ndim==3\n\n    print(f\"{sname}: RLE encoding result\")\n    for iz in range(preds_bool.shape[0]):\n        #pd_ids.append(f\"{sname}_{iz:04d}\")\n        pd_ids.append(f\"{sname}_{stems[iz]}\")\n\n        imgslice = preds_bool[iz,:,:]\n        predicted_rle = rle_encode(imgslice)\n        pd_rles.append(predicted_rle)\n    print(f\"{sname}: RLE encoding completed\")\n\n    print(f\"{sname}: Deleting all *.h5 files\")\n    delete_all_h5_files()","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:17:20.768871Z","iopub.execute_input":"2024-02-06T20:17:20.769278Z","iopub.status.idle":"2024-02-06T20:29:32.576453Z","shell.execute_reply.started":"2024-02-06T20:17:20.769248Z","shell.execute_reply":"2024-02-06T20:29:32.575349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # # debug\n\n# res = MLP_preds_on_h5files(['pred_0.h5', 'pred_1.h5', 'pred_2.h5'],\n#                             mlp_model=model_MLP_fusion, batch_size=16384 )\n#preds_bool=res","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:29:32.578494Z","iopub.execute_input":"2024-02-06T20:29:32.578843Z","iopub.status.idle":"2024-02-06T20:29:32.584337Z","shell.execute_reply.started":"2024-02-06T20:29:32.578813Z","shell.execute_reply":"2024-02-06T20:29:32.583158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create submission file","metadata":{}},{"cell_type":"code","source":"df = pd.DataFrame({'id': pd_ids, 'rle': pd_rles}).sort_values(by=['id'])\ndf.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:29:32.585756Z","iopub.execute_input":"2024-02-06T20:29:32.586110Z","iopub.status.idle":"2024-02-06T20:29:32.620826Z","shell.execute_reply.started":"2024-02-06T20:29:32.586082Z","shell.execute_reply":"2024-02-06T20:29:32.619783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:29:32.623530Z","iopub.execute_input":"2024-02-06T20:29:32.624337Z","iopub.status.idle":"2024-02-06T20:29:32.642267Z","shell.execute_reply.started":"2024-02-06T20:29:32.624298Z","shell.execute_reply":"2024-02-06T20:29:32.641147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Show random slices results","metadata":{}},{"cell_type":"markdown","source":"# Plotting\n\nPlots last volume","metadata":{}},{"cell_type":"code","source":"print(data0.shape)\nprint(preds_bool.shape)","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:29:32.644180Z","iopub.execute_input":"2024-02-06T20:29:32.644513Z","iopub.status.idle":"2024-02-06T20:29:32.649571Z","shell.execute_reply.started":"2024-02-06T20:29:32.644485Z","shell.execute_reply":"2024-02-06T20:29:32.648366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Show first examples from dset1_sub\nnimages=5\n\nidx = np.random.permutation( np.arange(preds_bool.shape[0]))[0:nimages]\nprint(idx)\nfig,axs = plt.subplots(len(idx),1,figsize=(7,len(idx)*7))\nfor i, idx0 in enumerate(idx):\n    datai=data0[idx0,:,:]\n    labeli=preds_bool[idx0,:,:]\n    #print(f\"i:{i}, datai shape:{datai.shape}, type:{datai.dtype}   labeli shape:{labeli.shape}, type:{labeli.dtype}\")\n    axs[i].imshow(datai, cmap=\"gray\")                       \n    axs[i].imshow(labeli,cmap='jet', alpha=0.4)\n    axs[i].set_axis_off()","metadata":{"execution":{"iopub.status.busy":"2024-02-06T20:29:45.872155Z","iopub.execute_input":"2024-02-06T20:29:45.872583Z","iopub.status.idle":"2024-02-06T20:29:47.365482Z","shell.execute_reply.started":"2024-02-06T20:29:45.872541Z","shell.execute_reply":"2024-02-06T20:29:47.364411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}