{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        #print(os.path.join(dirname, filename))\n        pass\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"from tqdm import tqdm\nimport re\nimport csv\nimport glob\nimport torch\n#import tensorflow as tf\n#import keras.backend as K\nimport concurrent.futures\nimport numpy as np\nimport os\nfrom skimage.filters import threshold_otsu\nimport random\nimport time\nimport cv2\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport seaborn as sns\ntry:\n    from skimage.io import imsave as imwrite\n    from skimage.io import imread\nexcept ImportError:\n    from cv2 import imread\n    from cv2 import imwrite\n\nimport openslide as ops\nfrom torchvision.utils import make_grid\nfrom torch.utils.tensorboard import SummaryWriter\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision\nfrom torchvision import models\nimport numpy as np\nimport torch.nn as nn\nfrom torchvision.transforms import transforms,Lambda\nimport torchvision.transforms.functional as TF\nimport random\nimport PIL\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"INPUT_DIR = '/kaggle/input/prostate-cancer-grade-assessment/'\ntrain_csv = f'{INPUT_DIR}/train.csv'\ntest_csv = f'{INPUT_DIR}/test.csv'\nsample_sub = f'{INPUT_DIR}/sample_submission.csv'\ntest_img_dir = f'{INPUT_DIR}/test_images'\ntrain_img_dir = f'{INPUT_DIR}/train_images'\n#model_weight_path = '/kaggle/input/approch-3-epoch-1/run_1_checkpoint_best_1.pth'\nmodel_weight_path = '/kaggle/input/approach3epoch3/run_1_256_checkpoint_best_3.pth'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_df = pd.read_csv(sample_sub)\nsample_df.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = pd.read_csv(test_csv)\nfor imgId in test_df['image_id']:\n    print(imgId)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = pd.read_csv(train_csv,index_col =\"image_id\")\n\ntrain_df.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class PANDAInferenceDataset():\n    def __init__(self,imageName,\n                 wsi_level_to_read_patch=0,\n                 wsi_level_to_process_wsi=1,\n                 patch_size=256,\n                 transform_inference = None,\n                 plot = True,\n                 test_img_dir=None):\n        \n        self.imageName = imageName\n        self.wsi_level_to_read_patch = wsi_level_to_read_patch\n        self.wsi_level_to_process_wsi = wsi_level_to_process_wsi\n        self.patch_size = patch_size\n        self.test_img_dir = test_img_dir\n        self.area_thd = 0.5\n        self.transforms = transform_inference\n        self.plot = plot\n        \n        self.yxfmtLevel0 = None\n        self.get_locations()\n    \n    def get_locations(self):\n        filepath = os.path.join(self.test_img_dir,f'{self.imageName}.tiff')\n        self.wsiObj = ops.open_slide(filepath)\n        tissueMask = self.generate_tissue_mask(is_otsu = True)\n        \n        self.scale_factor_est = self.wsiObj.level_dimensions[0][0] //self.wsiObj.level_dimensions[self.wsi_level_to_process_wsi][0]\n        stride = self.patch_size // self.scale_factor_est\n        yxpoints = self.get_xy_points(tissueMask, stride=stride)\n        cord_factor = self.scale_factor_est\n        self.yxfmtLevel0 = [(y * cord_factor, x * cord_factor) for y, x in yxpoints]\n        #print('Total-points ',len(self.yxfmtLevel0))\n        if self.plot: \n            plt.figure(1)\n            plt.imshow(tissueMask)\n            H, W = tissueMask.shape\n            #cv2.imwrite(mask_path, np.uint8(tissueMask) * 255)\n            yxfmt = [(y//cord_factor, x//cord_factor) for y, x in  self.yxfmtLevel0]\n            if True:\n                img_box = np.zeros([H, W, 3], np.uint8)\n                img_box[:, :, 0] = np.uint8(tissueMask) * 255\n                img_box[:, :, 1] = np.uint8(tissueMask) * 255\n                img_box[:, :, 2] = np.uint8(tissueMask) * 255\n                for y, x in yxfmt:\n                    cv2.rectangle(img_box, (x, y), (x + stride, y + stride), (0, 0, 255), 2)\n\n                #mask_path = os.path.join(self.masksaveFolder, f'{filename}_mask_level_{wsiLevel}_box.png')\n                #cv2.imwrite(mask_path, img_box)\n            plt.figure(figsize=(15,9))\n            plt.imshow(img_box)\n            \n        \n        #stride = self.patch_size // (2**self.wsi_level_to_process_wsi)\n        #yxpoints = self.get_xy_points(tissueMask, stride=stride)\n        #cord_factor = 2 ** (self.wsi_level_to_process_wsi)\n        #self.yxfmtLevel0 = [(y * cord_factor, x * cord_factor) for y, x in yxpoints]\n        \n    def generate_tissue_mask(self,is_otsu = True):\n        grayData = np.array(self.wsiObj.read_region(size=self.wsiObj.level_dimensions[self.wsi_level_to_process_wsi],\n                                               location=(0, 0), level=self.wsi_level_to_process_wsi).convert('L'))\n        # grayData = cv2.cvtColor(tissue_at_level, cv2.COLOR_BGR2GRAY)\n        if is_otsu:\n            try:\n                thd = threshold_otsu(grayData)\n            except:\n                thd = 255\n            tissueMask = grayData < thd\n        return tissueMask\n    \n    def get_xy_points(self,maskImg,stride):\n        H,W = maskImg.shape\n        area_thd = stride * stride * self.area_thd\n        yxpairList = []\n        if True:\n            x_grid = np.arange(0, W , stride)\n            y_grid = np.arange(0, H , stride)\n            for y in y_grid:\n                for x in x_grid:\n                    if np.sum(maskImg[y:y + stride, x:x + stride]) > area_thd:\n                        yxpairList.append((y,x))\n        return yxpairList\n    \n    def __len__(self):\n        return len(self.yxfmtLevel0)\n    \n    def __getitem__(self, index):\n        Y, X = self.yxfmtLevel0[index]\n        imgPatch = self.wsiObj.read_region(location=(X, Y),\n                                           level=self.wsi_level_to_read_patch,\n                                            size=(self.patch_size, self.patch_size)).convert('RGB')\n\n        # already a PIL Image\n        imgPatch = np.asarray(imgPatch)\n\n        if self.transforms is not None:\n            imgPatch = self.transforms(imgPatch)\n        \n        else:\n            raise print('Give valid transform')\n        \n        return imgPatch","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"inferenceTransfom = transforms.Compose([transforms.ToTensor(),\n                                       transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[1, 1, 1])])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Get model\nnum_class = 4\nmodel = models.resnet50(pretrained=False)\nif False:\n    wgtdict = torch.load(modelWeightsPath)\n    model.load_state_dict(wgtdict, False)\n    model.fc = nn.Linear(model.fc.in_features, num_class)\n    print(model)\nelse:\n    model.fc = nn.Linear(model.fc.in_features, num_class)\n    wgtdict = torch.load(model_weight_path)\n    model.load_state_dict(wgtdict['state_dict'], True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def Inference(model,dataloder,dataLength,batch_size,device,debug=False,folder_path = './'):\n    nLength = dataLength\n    result_dict = {'0':0,'1':0,'2':0,'3':0}\n    if debug:\n        probs = torch.cuda.FloatTensor(nLength,self.num_classes) if torch.cuda.is_available() else torch.FloatTensor(nLength,self.num_classes)\n    else:\n        probs = torch.cuda.FloatTensor(nLength,2) if torch.cuda.is_available() else torch.FloatTensor(nLength,2)\n    with torch.no_grad():\n        for batchIdx, imgdata in enumerate(dataloder):\n            inputs = imgdata.float().to(device)\n            outputs = model(inputs)\n            predict_proba = outputs.softmax(dim=1)\n            predProbMax, predictID = torch.max(predict_proba.data, 1)\n            #print('Valid-Inference\\tEpoch: [{}/{}]\\tPatches: [{}/{}]'.format(epoch, self.num_epoch, self.batch_size*(batchIdx + 1), nLength))\n            #output = F.softmax(model(input), dim=1)\n            #print(inputs.size(0),predict_proba.size(0))\n            if debug:\n                probs[batchIdx * batch_size:batchIdx * batch_size + inputs.size(0),:] = predict_proba.detach()[0:inputs.size(0), :].clone()\n            else:\n                probs[batchIdx * batch_size:batchIdx * batch_size + inputs.size(0),0] = predProbMax.detach()[0:inputs.size(0)].clone()\n                probs[batchIdx * batch_size:batchIdx * batch_size + inputs.size(0),1] = predictID.detach()[0:inputs.size(0)].clone()\n        return probs.cpu().numpy()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"label_to_gleason_score = {'0':0,'1':3,'2':4,'3':5} #0==negative\ngleason_to_isup_score = {'3+3':1,'3+4':2,'4+3':3,'4+4':4,'3+5':4,'5+3':4,'4+5':5,'5+4':5,'5+5':5} #otherwise =0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_isup_score(prob_freq):\n    g0 = prob_freq[0]\n    g3 = prob_freq[1]\n    g4 = prob_freq[2]\n    g5 = prob_freq[3]\n    if g3==0 and g4==0 and g5==0:\n        glason_score = '0+0'\n        try:\n            isup_score =  gleason_to_isup_score[glason_score]\n        except:\n            isup_score = 0\n    elif g3!=0 and g4==0 and g5==0:\n        glason_score = '3+3'\n        try:\n            isup_score =  gleason_to_isup_score[glason_score]\n        except:\n            isup_score = 0\n    elif g3==0 and g4!=0 and g5==0:\n        glason_score = '4+4'\n        try:\n            isup_score =  gleason_to_isup_score[glason_score]\n        except:\n            isup_score = 0\n    elif g3==0 and g4==0 and g5!=0:\n        glason_score = '5+5'\n        try:\n            isup_score =  gleason_to_isup_score[glason_score]\n        except:\n            isup_score = 0\n    else:\n        #case of 2 non -zero or all non zeros\n        tumors = prob_freq[1:]\n        max_idxs = np.argsort(tumors)\n        max_idxs = max_idxs+1\n        gleason_1 = label_to_gleason_score[str(max_idxs[-1])] \n        gleason_2 = label_to_gleason_score[str(max_idxs[-2])] \n        glason_score = f'{gleason_1}+{gleason_2}'\n        try:\n            isup_score = gleason_to_isup_score[glason_score]\n        except:\n            isup_score = 0\n    \n    return isup_score,glason_score","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = pd.read_csv(test_csv,index_col =\"image_id\")\nbatch_size = 32\nnum_worker = 4\npathc_size = 256\nplot = False\n#print(test_df.shape)\n#plt.figure(figsize=(15,9))\nuse_cuda = True\ndevice = torch.device(\"cuda\" if (use_cuda and torch.cuda.is_available()) else \"cpu\")\nmodel.to(device)\nmodel.eval()\nresults = []\nif os.path.exists(test_img_dir):\n    for imgId in test_df.index:#['image_id'][:10]:\n        dsInfer = PANDAInferenceDataset(imageName=imgId,\n                                        wsi_level_to_read_patch=0,\n                                        wsi_level_to_process_wsi=1,\n                                        patch_size=pathc_size,\n                                        plot = plot,\n                                        transform_inference = inferenceTransfom,\n                                        test_img_dir=test_img_dir)\n        dlInfer = DataLoader(dsInfer,\n                             batch_size=batch_size,\n                             num_workers= num_worker,\n                             pin_memory=False, \n                             shuffle=False,\n                             drop_last=False)\n        dataLength = dsInfer.__len__()\n        prob_info = Inference(model=model,\n                              dataloder=dlInfer,\n                              dataLength=dataLength,\n                              batch_size=batch_size,\n                              device=device,\n                              debug=False,\n                              folder_path = './')\n        yx = np.where(prob_info[:,0] > 0.90)\n        filter_probs = prob_info[yx]\n        #nd = np.lexsort((filter_probs[:,1],filter_probs[:,0])) \n        #print(filter_probs[nd,0],filter_probs[nd,1])\n        #need to decide fiter on hightest prob or highers number\n        prob_freq = np.bincount(filter_probs[:,1].astype(np.int64),minlength=4)\n    #     max_idxs = np.argsort(prob_freq)\n    #     gleason_1 = label_to_gleason_score[str(max_idxs[-1])] if prob_freq[max_idxs[-1]] > 0 else 0\n    #     gleason_2 = label_to_gleason_score[str(max_idxs[-2])] if prob_freq[max_idxs[-2]] > 0 else gleason_1\n    #     isup_key = f'{gleason_1}+{gleason_2}'\n    #     try:\n    #         score = gleason_to_isup_score[isup_key]\n    #     except:\n    #         score = 0\n        isup,gleason = get_isup_score(prob_freq)\n        #print(imgId,train_df.loc[imgId]['isup_grade'],train_df.loc[imgId]['gleason_score'],isup,gleason,prob_freq)\n        result = {\n                'image_id': imgId,\n                'isup_grade': isup}\n        results.append(result)\n\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ntest_df = pd.DataFrame(results, columns=['image_id', 'isup_grade'])\ntest_df.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if False:\n    img = next(iter(dlInfer))\n    print(img.shape)\n    img1 = np.uint8((img[10,...].permute(1,2,0).cpu().numpy()+0.5)*255)\n    for i in range(5):\n        img1 = np.uint8((img[i,...].permute(1,2,0).cpu().numpy()+0.5)*255)\n        plt.imshow(img1)\n        plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}