{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"!pip install /kaggle/input/timm-package/timm-0.1.26-py3-none-any.whl\n# os.listdir('../input/timm-package/')\nPKGPATH='../input/kprostate111/prostatev111'\nimport os\nimport gc\nimport sys\nsys.path.append(PKGPATH)\nimport glob\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nos.environ['KMP_DUPLICATE_LIB_OK']='True'\nimport sys\nfrom tqdm import tqdm \nfrom scipy import ndimage\nfrom matplotlib import pyplot as plt\nfrom string import ascii_lowercase\nimport math\nimport timm\nimport random\nimport time\nimport cv2\nimport optparse\nimport skimage.io\nfrom skimage.io import MultiImage\nfrom PIL import Image\nimport torch\nimport torch.nn.functional as F\nfrom torch import nn\nimport torch.optim as optim\nimport albumentations as A\nfrom torch.utils.data import Dataset\nfrom torch.utils.data import DataLoader\nfrom fastai.vision import AdaptiveConcatPool2d, Flatten\n#from torch.cuda.amp import GradScaler\nfrom collections import OrderedDict\nimport warnings \nwarnings.filterwarnings(\"ignore\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from utils.imageutils import rotatecrop, pairrot, cropcoords, noisecrop, Mish\nfrom utils.imageutils import padsplit, padimg, pixctr, cropper, condenseImgls\nfrom utils.imageutils import padsplitv2, chunk_squaresv2, condenseImglsv2, cropperv2\nfrom utils.imageutils import chunk_squares, frame_combine, balancedSampler\nfrom utils.utilities import get_logger, dumpobj, loadobj, Identity\nfrom utils.utilities import SpatialDropout, qwk5","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"logger = get_logger('Sequence model :', 'INFO') \ndevice=torch.device('cuda' if torch.cuda.is_available() else 'cpu')\ntry:\n    logger.info('Device : {}'.format(torch.cuda.get_device_name(0)))\nexcept:\n    logger.info('Device : Not available')\n\nlogger.info('Cuda available : {}'.format(torch.cuda.is_available()))\nn_gpu = torch.cuda.device_count()\nlogger.info('Cuda n_gpus : {}'.format(n_gpu ))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"NPIXELS=20*10**6\nNSAMP=300 #9999999\nDATATYPE = 'test'\nINPATH = '../input/prostate-cancer-grade-assessment'\nSAMPLE = f'{INPATH}/sample_submission.csv'\nDATA = f'{INPATH}/{DATATYPE}_images'\nsubdf = pd.read_csv(f'{INPATH}/sample_submission.csv')\ntstdf = pd.read_csv(f'{INPATH}/{DATATYPE}.csv')#TRAIN).head(30)#SAMPLE)\nif DATATYPE=='train':\n    folds= pd.read_csv(f'{INPATH}/../train-clust/train_clust.csv.gzip', \n                   usecols = ['image_id', 'fold'],\n                   compression = 'gzip')\n    removedf = pd.read_csv('../input/remove/removedf.csv')\n    alldf = pd.read_csv( f'{INPATH}/{DATATYPE}.csv')\n    alldf = alldf[~alldf.image_id.isin(removedf.imgname)]\n    alldf = pd.merge(alldf, folds, on='image_id')\n    tstdf = alldf.query('fold == 0').reset_index(drop=True)[:NSAMP]\n    print(tstdf.isup_grade.value_counts())\nprint(tstdf.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class options:\n    max_len = 36\n    tilesize = 224\n    data_path =   f'{DATATYPE}_images'\n    bsize = 2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def cropload(imname, thresh = 255):\n    # Read image\n    img = MultiImage(imname)[1]\n    \n    # Crop image\n    krows = np.where(np.min(img, 0) < 255)[0]\n    kcols = np.where(np.min(img, 1) < 255)[0]\n    img = img[kcols[0]: kcols[-1] + 1, krows[0]: krows[-1] + 1] \n    \n    return img\n\nval_transforms = A.Compose([\n    A.RandomCrop(224*6, 224*6, always_apply=True, p=1),\n    A.NoOp(),\n    ])\n    \ndef get_tiles(img, mode, n_tiles , tile_size, cutoff = 230, tile_cutoff = 0.0):\n        result = []\n        h, w, c = img.shape\n        pad_h = (tile_size - h % tile_size) % tile_size + ((tile_size * mode) // 2)\n        pad_w = (tile_size - w % tile_size) % tile_size + ((tile_size * mode) // 2)\n\n        img2 = np.pad(img,[[pad_h // 2, pad_h - pad_h // 2], [pad_w // 2,pad_w - pad_w//2], [0,0]], constant_values=255)\n        # Start of  #13 insert\n        # Make smaller slices and remove again\n        slice_size = 2\n        img3 = img2.reshape( \\\n            img2.shape[0] // tile_size, \\\n            tile_size , \\\n            img2.shape[1]* slice_size  // tile_size, \\\n            tile_size // slice_size, \\\n            3 \\\n        )\n        img3 = img3.transpose(0,2,1,3,4).reshape(-1, tile_size, tile_size//slice_size,3)\n\n        # Remove near blank tiles\n        bb, hh, ww, cc = img3.shape\n        idx = (img3[:,:,:,1].reshape(bb,-1) < cutoff).sum(1) > (hh*ww)*tile_cutoff\n        img3 = img3[idx]\n\n        # Join slices back to tiles\n        img3 = np.pad(img3,[[0, slice_size - (img3.shape[0] % slice_size)],[0,0],[0,0],[0,0]], constant_values=255)\n\n\n        img3 = np.concatenate(img3, 1) \\\n                        .reshape(tile_size, img3.shape[0]//slice_size, tile_size, 3)\\\n                        .transpose(1,0,2,3).reshape(-1, tile_size, tile_size,3)\n\n        ## End of  #13 insert        \n        #n_tiles_with_info = (img3.reshape(img3.shape[0],-1).sum(1) < tile_size ** 2 * 3 * 255).sum()\n\n        if len(img3) < n_tiles:\n            padder = n_tiles-len(img3)\n            img3 = np.pad(img3,[[padder//2,padder-(padder//2)],[0,0],[0,0],[0,0]], constant_values=255)\n\n\n        idxs = sorted(np.argsort((img3.reshape(img3.shape[0],-1) < cutoff) .sum(-1))[-n_tiles:])\n        img3 = img3[idxs]\n\n        return img3, 0 #n_tiles_with_info >= n_tiles\n\n\n        \ndef chunks(lst, n):\n    \"\"\"Yield successive n-sized chunks from lst.\"\"\"\n    for i in range(0, len(lst), n):\n        yield lst[i:i + n]\n\ntst_transforms = A.Compose([\n        A.Transpose(p=0.5),\n        A.VerticalFlip(p=0.5),\n        A.HorizontalFlip(p=0.5),\n    ])\n\nclass ProstateDataset(Dataset):\n    def __init__(self, df, path, transform, \n                 tile_mode=0, modtype='train'):\n        self.path = path\n        self.data_path = options.data_path\n        self.df = df\n        logger.info(f'Dataset {modtype} {self.df.shape}')\n        if modtype!='test':\n            self.df.gleason_score = self.df.gleason_score.str.replace('negative', '0+0')\n        # self.max_len = n_tiles # Max image ct in seq, filtered on % or filled pixels\n        self.gleasonmap = {'0': 0, '3': 1, '4': 2, '5': 3}\n        self.tile_mode = tile_mode\n        self.basesz = 224*6\n        self.transform = transform\n        self.type = modtype\n\n        \n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n\n        imname = self.df.iloc[idx].image_id\n        imgpath = f'{INPATH}/{self.data_path}/{imname}.tiff'\n        mskpath = f'{INPATH}/{self.data_path}/{imname}_mask.png'\n        imgorig = cropload(imgpath, thresh = 255) # cv2.imread(imgpath)\n        BASESZ = 224*6\n        # img = self.transform(image=img)['image']\n        sample = {}\n        for iii in range(4):\n            img = imgorig.copy()\n            for _ in range(iii):\n                img = np.rot90(img)\n            hhh, www, _ = img.shape\n            thresh = 230 # random.randint(230)\n            BASE = (img[:,:, 1]<thresh).sum()\n            FILLED_RATIO= 0\n            n_tiles = 1\n            image_size = 2000\n            while ((FILLED_RATIO)<0.85) and (image_size>228):\n                n_tiles += 1\n                image_size = BASESZ//n_tiles\n                image_size = int(image_size + (4-image_size%4))\n                tiles, OK = get_tiles(img, 2*random.randint(0,1), n_tiles**2, image_size, cutoff=thresh)   \n                FILLED = (tiles[:,:,:, 1]<thresh).sum() \n                FILLED_RATIO = FILLED/BASE\n            if FILLED_RATIO < 0.8: \n                dsize = (1+FILLED_RATIO)/2\n                img = cv2.resize(img, ( int(www * dsize), int(hhh * dsize) ), \\\n                                 interpolation=cv2.INTER_CUBIC)\n                BASE = (img[:,:, 1]<thresh).sum()\n                FILLED_RATIO= 0\n                n_tiles = 1\n                image_size = 2000\n                while ((FILLED_RATIO)<0.85) and (image_size>228):\n                    n_tiles += 1\n                    image_size = BASESZ//n_tiles\n                    image_size = int(image_size + (4-image_size%4))\n                    tiles, OK = get_tiles(img, 2*random.randint(0,1), n_tiles**2, image_size, cutoff=thresh)   \n                    FILLED = (tiles[:,:,:, 1]<thresh).sum() \n                    FILLED_RATIO = FILLED/BASE\n            fillls = []\n            if FILLED_RATIO < 0.9: \n                tilels = []\n                for  tile_cutoff in [0.0, 0.1, 0.2]:\n                    tilels.append(get_tiles(img, 2*random.randint(0,1), n_tiles**2, image_size, cutoff=thresh, tile_cutoff = tile_cutoff )[0])\n                    fillls.append((tilels[-1][:,:,:, 1]<thresh).sum()/BASE)  \n                fillls = np.array(fillls).round(3)\n                tiles = tilels[np.argmax(fillls)]\n            else:\n                fillls = np.array([FILLED_RATIO])\n            logtxt = f'flip {iii} img size {image_size} init filled {FILLED_RATIO:.4f}'\n            image_size = tiles.shape[1]            \n            n_row_tiles = int(np.sqrt(tiles.shape[0]))\n            images = np.zeros((image_size * n_row_tiles, image_size * n_row_tiles, 3))\n            for h in range(n_row_tiles):\n                for w in range(n_row_tiles):\n                    i = h * n_row_tiles + w\n                    this_img = tiles[i]\n                    h1 = h * image_size\n                    w1 = w * image_size\n                    images[h1:h1+image_size, w1:w1+image_size] = this_img\n            images = images.astype(np.uint8)\n            images = 255 - images\n            images = self.transform(image=images)['image']\n            images = images.astype(np.float32)\n            images /= 255\n            images = images.transpose(2, 0, 1)\n            sample[f'image{iii}'] = images\n        if self.type=='train':\n            sample['isup_grade'] = torch.zeros(5)\n            sample['isup_grade'][: self.df.iloc[idx].isup_grade ] = 1.\n            sample['gleason1'], sample['gleason2'] = map(self.gleasonmap.get, \\\n                        self.df.gleason_score.iloc[idx].split('+'))\n        return sample\n\ndef collatefn(batch):\n    # Remove error reads\n    batch = [b for b in batch if b is not None]\n    b = dict( (f'image{i}', torch.stack([torch.tensor(l[f'image{i}']) for l in batch])) for i in range(4))\n    # Add labels\n    if 'isup_grade' in batch[0]:\n        b['isup_grade'] = torch.stack([i['isup_grade'] for i in batch])\n        for ii in ['gleason1', 'gleason2']:\n            b[ii] =  torch.tensor([l[ii] for l in batch])\n    return b","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trndataargs = {'path': INPATH}\ntstdataset = ProstateDataset(tstdf, modtype=DATATYPE, transform = val_transforms, **trndataargs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#for t, batch in enumerate(tstdataset): \n#    if t>1: break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Image.fromarray( cv2.resize(((batch['image0']*255).astype(np.uint8)).transpose(1,2,0), (256, 256)) )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loaderls = []\ntrnloaderargs = {'num_workers' : 4, 'collate_fn' : collatefn}\ntstloader = DataLoader(tstdataset, shuffle=False, batch_size=options.bsize, **trnloaderargs) ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#batch = next(iter(tstloader))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class SeqNet(nn.Module):\n    def __init__(self, architecture = 'mixnet_m', pretrained=True, \\\n                 dense_units = 256, dropout = 0.2, isuplabels = 5, \\\n                 nblocks=4, concatfinal = 1,\n                 glabels = 4):\n        # Only resnet is supported in this version\n        super(SeqNet, self).__init__()\n        logger.info('Architecture {} dense {} dropout {}'.format( \\\n                            architecture, dense_units, dropout))\n        self.arch=architecture\n        if 'eff' in self.arch: \n            self.bbmod = timm.create_model(architecture, pretrained)\n            self.dense_units = dense_units\n            self.bbmod.classifier = Identity()\n            self.myctfc = nn.Linear(self.bbmod.num_features, isuplabels)\n\n    def forward(self, x):\n        emb = self.bbmod(x)\n        out_isup = self.myctfc(emb)\n        return out_isup\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"models = []\nfor cpt_path in sorted(glob.glob('../input/mnetlv33/*')):\n    logger.info(f'Load {cpt_path}')\n    models.append(SeqNet(architecture = 'tf_efficientnet_b0_ns', pretrained=False, nblocks=4, concatfinal = 1,\\\n                 dense_units = 256, dropout = 0.0, isuplabels = 5, glabels = 4))\n    cpt = torch.load(cpt_path, map_location=torch.device(device))\n    models[-1].load_state_dict(cpt)\n    models[-1].to(device);\n    models[-1].eval();\n    del cpt\n    gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ttafns = [\n        lambda x: x,\n        lambda x: x.flip(-1),\n        lambda x: x.flip(-2),\n        lambda x: x.flip(-1, -2),\n        lambda x: x.transpose(-1, -2),\n        lambda x: x.transpose(-1, -2).flip(-1),\n        lambda x: x.transpose(-1, -2).flip(-2),\n        lambda x: x.transpose(-1, -2).flip(-1, -2),\n        ]\n\niters = 4\nmodlens = len(models)\nif os.path.exists(f'{INPATH}/{DATATYPE}_images/'):\n    predsls = []\n    for loader in [tstloader]:\n        with torch.no_grad():\n            ypredval = []\n            for step, batch in enumerate(loader):\n                batchls = []\n                for i in range(iters):\n                    x = batch[f'image{i}'].to(device, dtype=torch.float)\n                    for midx in range(modlens):                     \n                        for f in ttafns:\n                            outisup = models[midx](f(x))\n                            outisup = torch.sigmoid(outisup)\n                            batchls.append(outisup)      \n                out = sum(batchls)/len(batchls)\n                out = out.cpu().sum(1).detach().numpy()\n                # logger.info([b.cpu().numpy().sum(1).round(2) for b in batchls])\n                # logger.info(50*'-')\n                # logger.info(f'{out.round(2)}  {batch[\"isup_grade\"].sum(1)}')\n                ypredval.append(out)\n                #logger.info(f'outval : {ypredval[-1]} act : {batch[\"isup_grade\"].sum(1)}')\n                del x, batch\n                if step%10==0:\n                    logger.info('Val step {} of {}'.format(step, len(loader)))  \n                    torch.cuda.empty_cache()\n                    gc.collect()\n            predsls.append(np.concatenate(ypredval, 0))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"subdf = tstloader.df[['image_id']]\nsubdf['isup_grade'] = (sum(predsls)/len(predsls)).round().astype(np.int32)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"subdf.to_csv(\"submission.csv\", index=False)\nsubdf.head(20)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if DATATYPE=='train':\n    logger.info((subdf.isup_grade == tstloader.df.isup_grade).value_counts())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if DATATYPE=='train':\n    logger.info(qwk5(subdf.isup_grade,  tstloader.df.isup_grade))","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}