{"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":"markdown","source":"# WELCOME\n\n**Here in this notebook we will take a look on how to operate with DICOM files format.**","metadata":{}},{"cell_type":"code","source":"# First, let's import useful pyhton libraries\nimport pydicom\nfrom tqdm import tqdm\nimport pandas as pd\nfrom matplotlib import pyplot as plt\nimport os\nimport time\nimport numpy as np\nimport cv2\nimport numpy as np","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:24.300510Z","iopub.execute_input":"2022-04-15T22:47:24.300749Z","iopub.status.idle":"2022-04-15T22:47:24.704837Z","shell.execute_reply.started":"2022-04-15T22:47:24.300683Z","shell.execute_reply":"2022-04-15T22:47:24.703336Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's take a look on the training csv file.\n\ntrain_df = pd.read_csv('../input/unifesp-xray-bodypart-classification/train.csv')","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:24.709568Z","iopub.execute_input":"2022-04-15T22:47:24.712269Z","iopub.status.idle":"2022-04-15T22:47:24.736600Z","shell.execute_reply.started":"2022-04-15T22:47:24.712227Z","shell.execute_reply":"2022-04-15T22:47:24.735959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head(8)","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:24.737868Z","iopub.execute_input":"2022-04-15T22:47:24.738106Z","iopub.status.idle":"2022-04-15T22:47:24.851012Z","shell.execute_reply.started":"2022-04-15T22:47:24.738072Z","shell.execute_reply":"2022-04-15T22:47:24.850336Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Let's  see our Target distribution\n\nbodyparts = {\n0 : 'Abdomen' ,\n1 :'Ankle' ,\n2 :'Cervical Spine',\n3 : 'Chest' ,\n4 :'Clavicles' ,\n5 :'Elbow' ,\n6 :'Feet' ,\n7 : 'Finger' ,\n8 : 'Forearm' ,\n9 : 'Hand' ,\n10 : 'Hip' ,\n11 : 'Knee' ,\n12 : 'Lower Leg' ,\n13 : 'Lumbar Spine' ,\n14 : 'Others' ,\n15 :'Pelvis',\n16 :'Shoulder' ,\n17 :'Sinus' ,\n18 : 'Skull' ,\n19 : 'Thigh' ,\n20 :'Thoracic Spine',\n21: 'Wrist',\n}\n\nlabels_num = [value.split() for value in train_df['Target']]\nlabels_num_flat = list(map(int, [item for sublist in labels_num for item in sublist]))\nlabels = [\"\" for _ in range(len(labels_num_flat))]\nfor i in range(len(labels_num_flat)):\n    labels[i] = bodyparts[labels_num_flat[i]]\n\nfig, ax = plt.subplots(figsize=(15, 5))\npd.Series(labels).value_counts().plot(kind = 'bar', fontsize=14)","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:24.856912Z","iopub.execute_input":"2022-04-15T22:47:24.857165Z","iopub.status.idle":"2022-04-15T22:47:25.332901Z","shell.execute_reply.started":"2022-04-15T22:47:24.857103Z","shell.execute_reply":"2022-04-15T22:47:25.332202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#DICOM file formats contains meta-data that can be useful for deep learning model preprocessing\n#I'll use a funciton created by Felipe Kitamura to list the DICOM Tags from the files\n\ndef dcmtag2table(folder, list_of_tags):\n    \"\"\"\n    # Create a Pandas DataFrame with the <list_of_tags> DICOM tags\n    # from the DICOM files in <folder>\n    # Parameters:\n    #    folder (str): folder to be recursively walked looking for DICOM files.\n    #    list_of_tags (list of strings): list of DICOM tags with no whitespaces.\n    # Returns:\n    #    df (DataFrame): table of DICOM tags from the files in folder.\n    \"\"\"\n    list_of_tags = list_of_tags.copy()\n    items = []\n    table = []\n    filelist = []\n    print(\"Listing all files...\")\n    start = time.time()\n    for root, dirs, files in os.walk(folder, topdown=False):\n        for name in files:\n            filelist.append(os.path.join(root, name))\n    print(\"Time: \" + str(time.time() - start))\n    print(\"Reading files...\")\n    time.sleep(2)\n    for _f in tqdm(filelist):\n        try:\n            ds = pydicom.dcmread(_f, stop_before_pixels=True)\n            items = []\n            items.append(_f)\n\n            for _tag in list_of_tags:\n                if _tag in ds:\n                    items.append(ds.data_element(_tag).value)\n                else:\n                    items.append(\"Not found\")\n\n            table.append((items))\n        except:\n            print(\"Skipping non-DICOM: \" + _f)\n\n            \n    list_of_tags.insert(0, \"Filename\")\n    test = list(map(list, zip(*table)))\n    dictone = {}\n\n    for i, _tag in enumerate (list_of_tags):\n        dictone[_tag] = test[i]\n\n    df = pd.DataFrame(dictone)\n    time.sleep(2)\n    print(\"Finished.\")\n    return df","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:25.334558Z","iopub.execute_input":"2022-04-15T22:47:25.335043Z","iopub.status.idle":"2022-04-15T22:47:25.345601Z","shell.execute_reply.started":"2022-04-15T22:47:25.335006Z","shell.execute_reply":"2022-04-15T22:47:25.344956Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tags = ['PhotometricInterpretation','BitsAllocated', 'SOPInstanceUID' ]\ndicom_tags_train =  dcmtag2table('../input/unifesp-xray-bodypart-classification/train', tags)","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:25.346776Z","iopub.execute_input":"2022-04-15T22:47:25.347046Z","iopub.status.idle":"2022-04-15T22:47:49.740989Z","shell.execute_reply.started":"2022-04-15T22:47:25.347011Z","shell.execute_reply":"2022-04-15T22:47:49.740140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dicom_tags_train.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:49.742130Z","iopub.execute_input":"2022-04-15T22:47:49.742381Z","iopub.status.idle":"2022-04-15T22:47:49.754262Z","shell.execute_reply.started":"2022-04-15T22:47:49.742344Z","shell.execute_reply":"2022-04-15T22:47:49.753400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Let's see the differente type of Photometric Interpreation and how it affects the display of an image\n\nprint(dicom_tags_train.PhotometricInterpretation.value_counts())\n\nprint('The following images are with Photometric Interpretation MONOCHROME1')\nn = 0\nfor idx,row in dicom_tags_train[dicom_tags_train.PhotometricInterpretation == 'MONOCHROME1'].iterrows():\n    dicom = pydicom.dcmread(row.Filename)\n    img = dicom.pixel_array\n    plt.imshow(img, cmap = 'gray')\n    plt.show()\n    n += 1\n    if n == 3:\n        break\n\nprint('The following images are with Photometric Interpretation MONOCHROME2')\n\nn = 0\nfor idx, row in dicom_tags_train[dicom_tags_train.PhotometricInterpretation == 'MONOCHROME2'].iterrows():\n    dicom = pydicom.dcmread(row.Filename)\n    img = dicom.pixel_array\n    plt.imshow(img, cmap = 'gray')\n    plt.show()\n    n += 1\n    if n == 3:\n        break","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:49.755910Z","iopub.execute_input":"2022-04-15T22:47:49.756670Z","iopub.status.idle":"2022-04-15T22:47:50.801496Z","shell.execute_reply.started":"2022-04-15T22:47:49.756631Z","shell.execute_reply":"2022-04-15T22:47:50.800686Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As you can see, the Photometric Interpretation changes hwo the density of the elements presents in the body will be shown. \nIn MONOCHROME1 the element in the image with less density (air) is brighter, the reverse happens in MONCHROME2","metadata":{}},{"cell_type":"code","source":"#You can use numpy invert() funciton to change the display of the Photometric Interpratation between two different MONCHROMEs\n\nprint('The following images are with Photometric Interpretation MONOCHROME1 but will be displayed as MONCHROME2')\nn = 0\nfor idx,row in dicom_tags_train[dicom_tags_train.PhotometricInterpretation == 'MONOCHROME1'].iterrows():\n    dicom = pydicom.dcmread(row.Filename)\n    img = dicom.pixel_array\n    plt.imshow(np.invert(img), cmap = 'gray')\n    plt.show()\n    n += 1\n    if n == 3:\n        break","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:50.802870Z","iopub.execute_input":"2022-04-15T22:47:50.803272Z","iopub.status.idle":"2022-04-15T22:47:51.330112Z","shell.execute_reply.started":"2022-04-15T22:47:50.803234Z","shell.execute_reply":"2022-04-15T22:47:51.329473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = dicom_tags_train.merge(train_df, on =  'SOPInstanceUID')","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:51.333119Z","iopub.execute_input":"2022-04-15T22:47:51.333312Z","iopub.status.idle":"2022-04-15T22:47:51.348645Z","shell.execute_reply.started":"2022-04-15T22:47:51.333288Z","shell.execute_reply":"2022-04-15T22:47:51.347946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:51.349941Z","iopub.execute_input":"2022-04-15T22:47:51.350185Z","iopub.status.idle":"2022-04-15T22:47:51.360983Z","shell.execute_reply.started":"2022-04-15T22:47:51.350151Z","shell.execute_reply":"2022-04-15T22:47:51.359961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#What about seeing how a baseline model works??\nimport tensorflow as tf\nfrom tensorflow.keras.utils import Sequence\nfrom tensorflow.keras.utils import to_categorical\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras import optimizers\nfrom tensorflow.keras.layers import Dense, Dropout\nfrom tensorflow.keras.layers import Conv2D\nfrom tensorflow.keras.layers import MaxPool2D, GlobalAveragePooling2D\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input, Concatenate, add\nfrom tensorflow.keras.callbacks import ModelCheckpoint\nfrom tensorflow.keras.layers import Activation, Dense, LeakyReLU\nfrom tensorflow.keras.applications.vgg16 import VGG16\nfrom tensorflow.keras.applications.nasnet import NASNetLarge\nfrom tensorflow.keras.applications import DenseNet121, EfficientNetB0\nfrom tensorflow.keras.models import Model, load_model\nfrom tensorflow.keras.layers import Dense, Dropout\nfrom tensorflow.keras.layers import Flatten\nfrom tensorflow.keras.optimizers import SGD, Adam\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.applications.densenet import preprocess_input\nfrom tensorflow.random import set_seed\nfrom tensorflow.keras.activations import sigmoid\n\nimport os\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn.metrics import auc\nfrom sklearn.metrics import roc_curve\nfrom sklearn.metrics import accuracy_score\nimport itertools\nfrom tensorflow.keras.models import load_model\n\nos.environ[\"CUDA_VISIBLE_DEVICES\"]=\"0\" # first gpu\nset_seed(1234)\n\ntf.config.list_physical_devices()","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:51.362297Z","iopub.execute_input":"2022-04-15T22:47:51.362681Z","iopub.status.idle":"2022-04-15T22:47:57.005146Z","shell.execute_reply.started":"2022-04-15T22:47:51.362644Z","shell.execute_reply":"2022-04-15T22:47:57.004311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reverse_train_labels = dict((v,k) for k,v in bodyparts.items())\n\ndef fill_targets(row):\n    row.Target = np.array(row.Target.split(\" \"))\n    for num in row.Target:\n        if num != '':\n            name = bodyparts[int(num)]\n            row.loc[name] = 1\n    return row","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.006472Z","iopub.execute_input":"2022-04-15T22:47:57.007166Z","iopub.status.idle":"2022-04-15T22:47:57.013339Z","shell.execute_reply.started":"2022-04-15T22:47:57.007127Z","shell.execute_reply":"2022-04-15T22:47:57.012646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for key in bodyparts.keys():\n    train_df[bodyparts[key]] = 0","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.014840Z","iopub.execute_input":"2022-04-15T22:47:57.015262Z","iopub.status.idle":"2022-04-15T22:47:57.031472Z","shell.execute_reply.started":"2022-04-15T22:47:57.015224Z","shell.execute_reply":"2022-04-15T22:47:57.030816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels = train_df.apply(fill_targets, axis=1)\ntrain_labels.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.034067Z","iopub.execute_input":"2022-04-15T22:47:57.034668Z","iopub.status.idle":"2022-04-15T22:47:57.502713Z","shell.execute_reply.started":"2022-04-15T22:47:57.034630Z","shell.execute_reply":"2022-04-15T22:47:57.502062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = dicom_tags_train.merge(train_labels, on =  'SOPInstanceUID')","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.504271Z","iopub.execute_input":"2022-04-15T22:47:57.504728Z","iopub.status.idle":"2022-04-15T22:47:57.515068Z","shell.execute_reply.started":"2022-04-15T22:47:57.504686Z","shell.execute_reply":"2022-04-15T22:47:57.514375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.516289Z","iopub.execute_input":"2022-04-15T22:47:57.517042Z","iopub.status.idle":"2022-04-15T22:47:57.536802Z","shell.execute_reply.started":"2022-04-15T22:47:57.517005Z","shell.execute_reply":"2022-04-15T22:47:57.536136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.iloc[:,5:]","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.538096Z","iopub.execute_input":"2022-04-15T22:47:57.538560Z","iopub.status.idle":"2022-04-15T22:47:57.557405Z","shell.execute_reply.started":"2022-04-15T22:47:57.538524Z","shell.execute_reply":"2022-04-15T22:47:57.556780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = ['Abdomen', 'Ankle', 'Cervical Spine',\n       'Chest', 'Clavicles', 'Elbow', 'Feet', 'Finger', 'Forearm', 'Hand',\n       'Hip', 'Knee', 'Lower Leg', 'Lumbar Spine', 'Others', 'Pelvis',\n       'Shoulder', 'Sinus', 'Skull', 'Thigh', 'Thoracic Spine', 'Wrist']","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.558665Z","iopub.execute_input":"2022-04-15T22:47:57.559097Z","iopub.status.idle":"2022-04-15T22:47:57.563789Z","shell.execute_reply.started":"2022-04-15T22:47:57.559062Z","shell.execute_reply":"2022-04-15T22:47:57.562968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class XrayDataLoader(tf.keras.utils.Sequence):\n    def __init__(self, data, batch_size, shuffle_df=True):\n        self.df = data\n        self.bs = batch_size\n\n        if shuffle_df == True:\n            self.df = self.df.sample(frac = 1.)\n        \n    def __len__(self):\n        return len(self.df) // self.bs\n\n    def __getitem__(self, idx):\n        start = idx * self.bs\n        end = (idx+1) * self.bs\n        \n        \n        \n        paths = self.df[start:end]\n        X = []\n        Y = []\n        \n        for j, path in paths.iterrows():\n            dcm = pydicom.dcmread(path.Filename)\n            img = dcm.pixel_array\n            \n            if np.random.choice([0,1]):\n                img = np.invert(img)\n            \n            if len(img.shape) > 2:\n                for i in range(0, len(img.shape[0])):\n                    img =  img[i, : , :]\n                    img = img / img.max() - 0.5\n                    #img = cv2.resize(img, (256, 256)) \n\n                    img = img.astype(np.float32)\n                    X.append(img)\n                    Y.append(path[5:])\n                    break\n            else:\n                img = img / img.max() - 0.5\n                #img = cv2.resize(img, (256, 256)) \n\n                img = img.astype(np.float32)\n                X.append(img)\n                Y.append(path[5:])  \n\n        X = np.repeat(np.asarray(X).astype(np.float32)[..., np.newaxis], 3, axis= 3)\n\n\n        Y = np.asarray(Y).astype(np.float32)\n\n        \n        return X, Y","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.565260Z","iopub.execute_input":"2022-04-15T22:47:57.565535Z","iopub.status.idle":"2022-04-15T22:47:57.577831Z","shell.execute_reply.started":"2022-04-15T22:47:57.565501Z","shell.execute_reply":"2022-04-15T22:47:57.577136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.579075Z","iopub.execute_input":"2022-04-15T22:47:57.579489Z","iopub.status.idle":"2022-04-15T22:47:57.586227Z","shell.execute_reply.started":"2022-04-15T22:47:57.579455Z","shell.execute_reply":"2022-04-15T22:47:57.585350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train, val = train_test_split(train,test_size =0.2, random_state= 42)","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.587499Z","iopub.execute_input":"2022-04-15T22:47:57.588185Z","iopub.status.idle":"2022-04-15T22:47:57.600382Z","shell.execute_reply.started":"2022-04-15T22:47:57.588151Z","shell.execute_reply":"2022-04-15T22:47:57.599615Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_gen = XrayDataLoader(train, 8)\nval_gen = XrayDataLoader(val, 8, shuffle_df = False)","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.601708Z","iopub.execute_input":"2022-04-15T22:47:57.603547Z","iopub.status.idle":"2022-04-15T22:47:57.608472Z","shell.execute_reply.started":"2022-04-15T22:47:57.603516Z","shell.execute_reply":"2022-04-15T22:47:57.607576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#train_gen[0][0].shape","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.609909Z","iopub.execute_input":"2022-04-15T22:47:57.610416Z","iopub.status.idle":"2022-04-15T22:47:57.617332Z","shell.execute_reply.started":"2022-04-15T22:47:57.610380Z","shell.execute_reply":"2022-04-15T22:47:57.616564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with tf.device('/device:gpu:0'):\n    callback_sv = ModelCheckpoint(filepath = './model.h5',\n    verbose=0,\n    save_best_only=True,\n    save_weights_only=False,\n    monitor=\"val_loss\",                           \n    mode=\"min\",\n    save_freq=\"epoch\")\n\n    callback_rl = ReduceLROnPlateau(\n    factor=0.5,\n    patience=10,\n    verbose=1,\n    min_lr =1e-7, \n    mode=\"auto\")\n\n    es = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=30)\n\n    callbacks =[callback_sv,callback_rl, es]\n\n    model = VGG16(include_top=False, input_shape=(256, 256, 3), weights=\"imagenet\")\n\n    # mark loaded layers as not trainable\n    for layer in model.layers:\n        layer.trainable = True\n\n        # add new classifier layers\n    flat1 = GlobalAveragePooling2D()(model.layers[-1].output)\n    flat2 = Dropout(0.3)(flat1)\n    class1 = Dense(64, activation='relu', kernel_initializer='he_uniform')(flat2)\n    class2 = Dense(32, activation='relu', kernel_initializer='he_uniform')(class1)\n    output = Dense(22, activation='sigmoid')(class2)\n\n    # define new model\n    model = Model(inputs=model.inputs, outputs=output)\n\n    # compile model\n    opt = Adam(lr=0.000001)#, momentum=0.9)\n    model.compile(optimizer=opt, loss=tf.keras.losses.CategoricalCrossentropy(), metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:47:57.619373Z","iopub.execute_input":"2022-04-15T22:47:57.620320Z","iopub.status.idle":"2022-04-15T22:48:00.504885Z","shell.execute_reply.started":"2022-04-15T22:47:57.620281Z","shell.execute_reply":"2022-04-15T22:48:00.503223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with tf.device('/device:gpu:0'):\n    history=model.fit(train_gen,steps_per_epoch=len(train_gen), validation_data=val_gen,\n              validation_steps=len(val_gen),epochs=50 , workers = 6,\n              max_queue_size =6, use_multiprocessing = True, callbacks= callbacks)","metadata":{"execution":{"iopub.status.busy":"2022-04-15T22:48:00.506106Z","iopub.execute_input":"2022-04-15T22:48:00.506345Z","iopub.status.idle":"2022-04-15T23:02:09.497057Z","shell.execute_reply.started":"2022-04-15T22:48:00.506308Z","shell.execute_reply":"2022-04-15T23:02:09.494404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## We will keep adding valuable information!\n#Enjoy the competition","metadata":{"execution":{"iopub.status.busy":"2022-04-15T23:02:09.499908Z","iopub.status.idle":"2022-04-15T23:02:09.500310Z","shell.execute_reply.started":"2022-04-15T23:02:09.500073Z","shell.execute_reply":"2022-04-15T23:02:09.500093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}