{"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_minor":4,"nbformat":4,"cells":[{"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\nfrom tqdm.auto import tqdm\nimport tifffile\nimport matplotlib.pyplot as plt\nimport random","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-12-21T20:37:53.824844Z","iopub.execute_input":"2021-12-21T20:37:53.825638Z","iopub.status.idle":"2021-12-21T20:37:54.118194Z","shell.execute_reply.started":"2021-12-21T20:37:53.825507Z","shell.execute_reply":"2021-12-21T20:37:54.117491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualising Flows\n#### 5-fold data Generated in cellpose format here: https://www.kaggle.com/ks2019/sartorius-train-tif","metadata":{}},{"cell_type":"code","source":"def plot_example(img_path):\n    mask_path = img_path.replace('img','masks')\n    flow_path = img_path.replace('img','flows')\n    img = tifffile.imread(img_path)\n    masks = tifffile.imread(mask_path)\n    flows = tifffile.imread(flow_path)\n\n    plt.figure(figsize=(25,10))\n    plt.subplot(2,3,1)\n    plt.axis('off')\n    plt.imshow(img)\n    plt.title('image')\n    plt.subplot(2,3,2)\n    plt.axis('off')\n    plt.imshow(masks)\n    plt.title('mask')\n    for k in range(4):\n        plt.subplot(2,3,3+k)\n        plt.axis('off')\n        plt.imshow(flows[k])\n        plt.title(f'flow {k}')\n    plt.show()\n    \nroot = '../input/sartorius-train-tif/fold_0/train/'\nsample_paths = os.listdir(root)\nsample_paths = [x for x in sample_paths if 'img' in x]\nrandom.shuffle(sample_paths)\nfor k in range(5):\n    img_path = sample_paths[k]\n    print(img_path)\n    plot_example(root+img_path)","metadata":{"execution":{"iopub.status.busy":"2021-12-21T20:37:54.768857Z","iopub.execute_input":"2021-12-21T20:37:54.769298Z","iopub.status.idle":"2021-12-21T20:37:58.857036Z","shell.execute_reply.started":"2021-12-21T20:37:54.769263Z","shell.execute_reply":"2021-12-21T20:37:58.856444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dependencies","metadata":{}},{"cell_type":"code","source":"!pip uninstall -y -q yellowbrick\n\n!pip install -q tifffile # contains tools to operate tiff-files\n!pip install -q folium==0.2.1\n!pip install -q imgaug==0.2.5\n!pip install -q opencv-python==3.4.5.20\n!pip install -q numpy==1.20.0\n!pip install -q cellpose \n!pip install -q wget\n!pip install -q memory_profiler\n!pip install -q fpdf","metadata":{"execution":{"iopub.status.busy":"2021-12-15T17:42:41.840124Z","iopub.execute_input":"2021-12-15T17:42:41.840733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Train","metadata":{}},{"cell_type":"code","source":"model_to_load = 'cyto' ## cyto, cyto2, nuclei\nnumber_of_epochs = 10  ## Train more epochs for better results\nbatch_size = 8\ninitial_learning_rate = 0.0002\nTraining_channel = 0 # For grayscale\nSecond_training_channel= 0 \ntrain_folder = '/tmp/cellpose_train/train'\ntest_folder = '/tmp/cellpose_train/val'\nFOLD = 2","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir -p /tmp/cellpose_train/\n\nimport glob\nroot = '../input/sartorius-train-tif/'\n!cp -r {root}/fold_{FOLD}/* /tmp/cellpose_train/","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:32:41.648303Z","iopub.execute_input":"2021-12-12T07:32:41.648809Z","iopub.status.idle":"2021-12-12T07:32:53.391587Z","shell.execute_reply.started":"2021-12-12T07:32:41.648758Z","shell.execute_reply":"2021-12-12T07:32:53.390582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls {train_folder} | wc -l\n!ls {test_folder} | wc -l","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:32:53.393397Z","iopub.execute_input":"2021-12-12T07:32:53.393715Z","iopub.status.idle":"2021-12-12T07:32:54.765627Z","shell.execute_reply.started":"2021-12-12T07:32:53.393664Z","shell.execute_reply":"2021-12-12T07:32:54.764842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python -m cellpose --train --use_gpu --fast_mode \\\n        --dir \"$train_folder\" --test_dir \"$test_folder\" \\\n        --pretrained_model $model_to_load \\\n        --chan $Training_channel --chan2 $Second_training_channel \\\n        --n_epochs $number_of_epochs \\\n        --learning_rate $initial_learning_rate \\\n        --batch_size $batch_size \\\n        --img_filter img \\\n        --mask_filter masks","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:32:54.767311Z","iopub.execute_input":"2021-12-12T07:32:54.767581Z","iopub.status.idle":"2021-12-12T07:37:00.388885Z","shell.execute_reply.started":"2021-12-12T07:32:54.767545Z","shell.execute_reply":"2021-12-12T07:37:00.386683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls -lh /tmp/cellpose_train/train/models","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:37:00.393674Z","iopub.execute_input":"2021-12-12T07:37:00.393938Z","iopub.status.idle":"2021-12-12T07:37:01.246723Z","shell.execute_reply.started":"2021-12-12T07:37:00.393906Z","shell.execute_reply":"2021-12-12T07:37:01.245619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!cp -r /tmp/cellpose_train/train/models .","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:37:01.248573Z","iopub.execute_input":"2021-12-12T07:37:01.248994Z","iopub.status.idle":"2021-12-12T07:37:01.981644Z","shell.execute_reply.started":"2021-12-12T07:37:01.248951Z","shell.execute_reply":"2021-12-12T07:37:01.98049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inference \n\nRefer: https://www.kaggle.com/slawekbiel/cellpose-inference-307-lb","metadata":{}},{"cell_type":"code","source":"model_path = glob.glob('models/*')[0]\nprint(model_path)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:37:01.983339Z","iopub.execute_input":"2021-12-12T07:37:01.983645Z","iopub.status.idle":"2021-12-12T07:37:01.989595Z","shell.execute_reply.started":"2021-12-12T07:37:01.983591Z","shell.execute_reply":"2021-12-12T07:37:01.988833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%writefile predict.py\nimport sys\nimport numpy as np\nfrom cellpose import models, io, plot\nfrom pathlib import Path\nimport pandas as pd\nfrom tqdm.auto import tqdm\nimport glob\n\ndef rle_encode(img):\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\ntest_files = glob.glob('/tmp/cellpose_train/val/*_img.tif')\nprint(len(test_files))\nmodel = models.CellposeModel(gpu=True, pretrained_model=sys.argv[1])\n\nids, masks = [],[]\nfor fn in tqdm(test_files):\n    id_ = fn.split('/')[-1].replace('_img.tif','')\n    preds, flows, _ = model.eval(io.imread(fn), diameter=19, channels=[0,0], augment=True, resample=True)\n    for i in range (1, preds.max() + 1):\n        ids.append(id_)\n        masks.append(rle_encode(preds == i))\n        \npd.DataFrame({'id':ids, 'predicted':masks}).to_csv('val_predictions.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:37:01.993748Z","iopub.execute_input":"2021-12-12T07:37:01.994315Z","iopub.status.idle":"2021-12-12T07:37:02.004156Z","shell.execute_reply.started":"2021-12-12T07:37:01.994277Z","shell.execute_reply":"2021-12-12T07:37:02.003422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python predict.py {model_path} /tmp/cellpose_train/val","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:37:02.00515Z","iopub.execute_input":"2021-12-12T07:37:02.006763Z","iopub.status.idle":"2021-12-12T07:40:37.508578Z","shell.execute_reply.started":"2021-12-12T07:37:02.006722Z","shell.execute_reply":"2021-12-12T07:40:37.507629Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Plot","metadata":{}},{"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\nimport skimage\nimport skimage.segmentation\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:40:37.510569Z","iopub.execute_input":"2021-12-12T07:40:37.510885Z","iopub.status.idle":"2021-12-12T07:40:38.155386Z","shell.execute_reply.started":"2021-12-12T07:40:37.510845Z","shell.execute_reply":"2021-12-12T07:40:38.154537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def rles_to_mask(encs, shape):\n    \"\"\"\n    Decodes a rle.\n\n    Args:\n        encs (list of str): Rles for each class.\n        shape (tuple [2]): Mask size.\n\n    Returns:\n        np array [shape]: Mask.\n    \"\"\"\n    img = np.zeros(shape[0] * shape[1], dtype=np.uint)\n    if type(encs)==float:\n        return img\n    for m, enc in enumerate(encs):\n        if isinstance(enc, np.float) and np.isnan(enc):\n            continue\n        enc_split = enc.split()\n        for i in range(len(enc_split) // 2):\n            start = int(enc_split[2 * i]) - 1\n            length = int(enc_split[2 * i + 1])\n            img[start: start + length] = 1 + m\n    return img.reshape(shape)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:40:38.156731Z","iopub.execute_input":"2021-12-12T07:40:38.157002Z","iopub.status.idle":"2021-12-12T07:40:38.164647Z","shell.execute_reply.started":"2021-12-12T07:40:38.156964Z","shell.execute_reply":"2021-12-12T07:40:38.163908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"width = 704\nheight = 520\nshape = [height,width]\n\ntrain_df = pd.read_csv('../input/sartorius-cell-instance-segmentation/train.csv')\ntrain_df = train_df.groupby('id').annotation.agg(list).reset_index()\n\ncellpose_predictions = pd.read_csv('val_predictions.csv')\ncellpose_predictions = cellpose_predictions.groupby('id').predicted.agg(list).reset_index()\ndf = pd.merge(train_df,cellpose_predictions,on='id')\n\nprint(df.shape)\n\ndf.sample(2)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:40:38.16642Z","iopub.execute_input":"2021-12-12T07:40:38.1669Z","iopub.status.idle":"2021-12-12T07:40:38.775645Z","shell.execute_reply.started":"2021-12-12T07:40:38.166856Z","shell.execute_reply":"2021-12-12T07:40:38.774903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i,row in df.iterrows():\n    \n    print(row.id)\n    gt_masks = rles_to_mask(row.annotation, shape).astype(np.uint16)\n    predicted_masks = rles_to_mask(row.predicted, shape).astype(np.uint16)\n    \n    gt_masks = (gt_masks>0).astype(int)*(gt_masks%5)\n    predicted_masks = (predicted_masks>0).astype(int)*(predicted_masks%5)\n\n    _, axs = plt.subplots(1, 2, figsize=(36, 18))\n    axs = axs.flatten()\n    axs[0].imshow(gt_masks)\n    axs[1].imshow(predicted_masks)\n    plt.show()\n    \n    if i==4: break","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:40:38.776767Z","iopub.execute_input":"2021-12-12T07:40:38.777761Z","iopub.status.idle":"2021-12-12T07:40:42.262039Z","shell.execute_reply.started":"2021-12-12T07:40:38.777721Z","shell.execute_reply":"2021-12-12T07:40:42.261307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Evaluate","metadata":{}},{"cell_type":"code","source":"def compute_iou(labels, y_pred):\n    \"\"\"\n    Computes the IoU for instance labels and predictions.\n\n    Args:\n        labels (np array): Labels.\n        y_pred (np array): predictions\n\n    Returns:\n        np array: IoU matrix, of size true_objects x pred_objects.\n    \"\"\"\n\n    true_objects = len(np.unique(labels))\n    pred_objects = len(np.unique(y_pred))\n\n    # Compute intersection between all objects\n    intersection = np.histogram2d(\n        labels.flatten(), y_pred.flatten(), bins=(true_objects, pred_objects)\n    )[0]\n\n    # Compute areas (needed for finding the union between all objects)\n    area_true = np.histogram(labels, bins=true_objects)[0]\n    area_pred = np.histogram(y_pred, bins=pred_objects)[0]\n    area_true = np.expand_dims(area_true, -1)\n    area_pred = np.expand_dims(area_pred, 0)\n\n    # Compute union\n    union = area_true + area_pred - intersection\n    iou = intersection / union\n    \n    return iou[1:, 1:]  # exclude background\n\ndef precision_at(threshold, iou):\n    \"\"\"\n    Computes the precision at a given threshold.\n\n    Args:\n        threshold (float): Threshold.\n        iou (np array [n_truths x n_preds]): IoU matrix.\n\n    Returns:\n        int: Number of true positives,\n        int: Number of false positives,\n        int: Number of false negatives.\n    \"\"\"\n    matches = iou > threshold\n    true_positives = np.sum(matches, axis=1) >= 1  # Correct objects\n    false_negatives = np.sum(matches, axis=1) == 0  # Missed objects\n    false_positives = np.sum(matches, axis=0) == 0  # Extra objects\n    tp, fp, fn = (\n        np.sum(true_positives),\n        np.sum(false_positives),\n        np.sum(false_negatives),\n    )\n    return tp, fp, fn\n\nfrom tqdm.auto import tqdm\ndef iou_map(truths, preds, verbose=0):\n    \"\"\"\n    Computes the metric for the competition.\n    Masks contain the segmented pixels where each object has one value associated,\n    and 0 is the background.\n\n    Args:\n        truths (list of masks): Ground truths.\n        preds (list of masks): Predictions.\n        verbose (int, optional): Whether to print infos. Defaults to 0.\n\n    Returns:\n        float: mAP.\n    \"\"\"\n    ious = [\n        compute_iou(rles_to_mask(truth,shape), rles_to_mask(pred,shape)) \n            for truth, pred in tqdm(zip(truths, preds))\n    ]\n    \n    if verbose:\n        print(ious[0].shape)\n        print(\"Thresh\\tTP\\tFP\\tFN\\tPrec.\")\n\n    prec = []\n    for t in np.arange(0.5, 1.0, 0.05):\n        tps, fps, fns = 0, 0, 0\n        for iou in ious:\n            tp, fp, fn = precision_at(t, iou)\n            tps += tp\n            fps += fp\n            fns += fn\n\n        p = tps / (tps + fps + fns)\n        prec.append(p)\n\n        if verbose:\n            print(\"{:1.3f}\\t{}\\t{}\\t{}\\t{:1.3f}\".format(t, tps, fps, fns, p))\n\n    if verbose:\n        print(\"AP\\t-\\t-\\t-\\t{:1.3f}\".format(np.mean(prec)))\n\n    return np.mean(prec)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:40:42.264379Z","iopub.execute_input":"2021-12-12T07:40:42.264702Z","iopub.status.idle":"2021-12-12T07:40:42.282709Z","shell.execute_reply.started":"2021-12-12T07:40:42.26466Z","shell.execute_reply":"2021-12-12T07:40:42.281448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"annotations = df.annotation.values\npredictions = df.predicted.values","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:40:42.284358Z","iopub.execute_input":"2021-12-12T07:40:42.284935Z","iopub.status.idle":"2021-12-12T07:40:42.296793Z","shell.execute_reply.started":"2021-12-12T07:40:42.284893Z","shell.execute_reply":"2021-12-12T07:40:42.29601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"iou_map(annotations,predictions,verbose=1)","metadata":{"execution":{"iopub.status.busy":"2021-12-12T07:40:42.298222Z","iopub.execute_input":"2021-12-12T07:40:42.298526Z","iopub.status.idle":"2021-12-12T07:40:47.329022Z","shell.execute_reply.started":"2021-12-12T07:40:42.298487Z","shell.execute_reply":"2021-12-12T07:40:47.328088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}