{"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":71549,"databundleVersionId":8561470,"sourceType":"competition"}],"dockerImageVersionId":30746,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install monai","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-09-10T06:02:39.445739Z","iopub.execute_input":"2024-09-10T06:02:39.446096Z","iopub.status.idle":"2024-09-10T06:02:51.762324Z","shell.execute_reply.started":"2024-09-10T06:02:39.446064Z","shell.execute_reply":"2024-09-10T06:02:51.761388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom monai.utils import first\nimport timm\nfrom monai.transforms import (\n    EnsureChannelFirstd,\n    Compose,\n    LoadImaged,\n    Spacingd,\n    NormalizeIntensityd,\n    MapTransform,\n    SpatialPadd,\n    ToTensord,\n    ConcatItemsd,\n    SqueezeDimd,\n    SpatialCrop,\n    Transposed,\n    Resize,\n    RandRotated,\n    RandGaussianNoised,\n    RandShiftIntensityd,\n    RandScaleIntensityd\n)\nfrom sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay,roc_curve,auc\n\nimport torch.nn.functional as F\nimport torch.nn as nn\nimport random\nfrom tqdm import tqdm\nfrom monai.networks.nets import DenseNet,EfficientNetBN\nfrom monai.data import CacheDataset, DataLoader,PersistentDataset,ThreadDataLoader\nfrom monai.config import print_config\nfrom monai.apps import download_and_extract\nimport torch\nimport matplotlib.pyplot as plt\nimport os\nfrom monai.config import KeysCollection\nfrom typing import Mapping, Hashable\nfrom sklearn .metrics import roc_auc_score\nimport os\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:02:51.764698Z","iopub.execute_input":"2024-09-10T06:02:51.765567Z","iopub.status.idle":"2024-09-10T06:03:19.927306Z","shell.execute_reply.started":"2024-09-10T06:02:51.765526Z","shell.execute_reply":"2024-09-10T06:03:19.926540Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train.csv\")\ntrain_df = train_df.set_index(\"study_id\")\ntrain_series_df = pd.read_csv(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_series_descriptions.csv\")\ntrain_series_df = train_series_df.set_index([\"study_id\",\"series_description\"])\nlabel_coord = pd.read_csv(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_label_coordinates.csv\")\nlabel_coord = label_coord.set_index([\"series_id\",\"condition\",\"level\"])","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:03:19.928455Z","iopub.execute_input":"2024-09-10T06:03:19.928729Z","iopub.status.idle":"2024-09-10T06:03:20.047275Z","shell.execute_reply.started":"2024-09-10T06:03:19.928705Z","shell.execute_reply":"2024-09-10T06:03:20.046493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df\n#train_series_df\n#label_coord","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:03:20.050071Z","iopub.execute_input":"2024-09-10T06:03:20.050681Z","iopub.status.idle":"2024-09-10T06:03:20.081718Z","shell.execute_reply.started":"2024-09-10T06:03:20.050644Z","shell.execute_reply":"2024-09-10T06:03:20.080781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_data = []\ntrain_path = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images\"\nlevels = [\"l1_l2\",\"l2_l3\",\"l3_l4\",\"l4_l5\",\"l5_s1\"]\nlabels_dic = {\n    \"Normal/Mild\" : 0,\n    \"Moderate\" : 1,\n    \"Severe\":2,\n}\n\nfor subject in tqdm(os.listdir(train_path)):\n    try:\n        t1_row = train_series_df.loc[int(subject),\"Sagittal T1\"]\n    except:\n        t1_row = train_series_df.loc[int(subject),\"Sagittal T2/STIR\"]\n    try:\n        t2_row = train_series_df.loc[int(subject),\"Sagittal T2/STIR\"]\n    except:\n        t2_row = train_series_df.loc[int(subject),\"Sagittal T1\"]\n\n    t1=t1_row[\"series_id\"].iat[0]\n    t2=t2_row[\"series_id\"].iat[0]\n    for l in levels:\n        for side in ['Left',\"Right\"]:\n            label_row = train_df.loc[int(subject)][side.lower()+ \"_neural_foraminal_narrowing_\"+l]\n            if isinstance(label_row, float):\n                continue\n            label = labels_dic[label_row]\n            try:\n                slice_ = label_coord.loc[int(t1),side+ \" Neural Foraminal Narrowing\" ,l.split(\"_\")[0].upper()+\"/\"+l.split(\"_\")[1].upper()]\n                if not slice_.empty:\n                    dic = {\n                        \"t1\": os.path.join(train_path,subject,str(t1)),\n                        \"t2\": os.path.join(train_path,subject,str(t2)),\n                        \"level\":side[0]+\"_\"+l,\n                        \"label\":label\n\n                    }\n                all_data.append(dic)\n            except:\n                continue","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:03:20.083031Z","iopub.execute_input":"2024-09-10T06:03:20.083388Z","iopub.status.idle":"2024-09-10T06:03:25.472045Z","shell.execute_reply.started":"2024-09-10T06:03:20.083355Z","shell.execute_reply":"2024-09-10T06:03:25.471117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"random.seed(1)\nrandom.shuffle(all_data)\nsplit = [.8,.1,.1]\ntrain_files = all_data[:int(len(all_data)*split[0])]\nval_files = all_data[int(len(all_data)*split[0]):int(len(all_data)*(split[0]+split[1]))]\ntest_files = all_data[int(len(all_data)*(split[0]+split[1])):]\nprint(len(train_files),len(val_files),len(test_files))","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:03:25.473164Z","iopub.execute_input":"2024-09-10T06:03:25.473509Z","iopub.status.idle":"2024-09-10T06:03:25.498184Z","shell.execute_reply.started":"2024-09-10T06:03:25.473476Z","shell.execute_reply":"2024-09-10T06:03:25.497287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SPACING = (.5,.5,-1)\nROI_SIZE = (128,128,3)\n\nclass RescaleLabeld(MapTransform):\n\n    def __call__(\n        self, data: Mapping[Hashable, np.ndarray]\n    ) -> Mapping[Hashable, np.ndarray]:\n        filename = data[\"t1_meta_dict\"][\"filename_or_obj\"].split(\"/\")[-1]\n \n        level = data[\"level\"]\n        x_scale = (data[\"t1_meta_dict\"][\"spacing\"][0])/SPACING[0]\n        y_scale = (data[\"t1_meta_dict\"][\"spacing\"][1])/SPACING[1]\n        \n        if level[0]==\"R\":\n            row = label_coord.loc[int(filename),\"Right Neural Foraminal Narrowing\" ,level.split(\"_\")[1].upper()+\"/\"+level.split(\"_\")[2].upper()]\n        else:\n            row = label_coord.loc[int(filename),\"Left Neural Foraminal Narrowing\" ,level.split(\"_\")[1].upper()+\"/\"+level.split(\"_\")[2].upper()]\n        \n        x,y,z = row[\"x\"]*x_scale,row[\"y\"]*y_scale,row[\"instance_number\"]-1\n        data[\"coord\"] = (x,y,z)\n        return data\nclass CustomSpatialCropd(MapTransform):      \n    def __call__(\n        self, data: Mapping[Hashable, np.ndarray]\n    ) -> Mapping[Hashable, np.ndarray]:\n        cropper = SpatialCrop(data[\"coord\"], ROI_SIZE)\n        d = dict(data)\n        for key in self.key_iterator(d):\n            d[key] = cropper(d[key])\n        return d\nclass CustomResized(MapTransform):\n            \n    def __call__(\n        self, data: Mapping[Hashable, np.ndarray]\n    ) -> Mapping[Hashable, np.ndarray]:\n        #print(data[\"t1\"].shape[1:])\n        self.resizer = Resize(spatial_size=data[\"t1\"].shape[1:])\n        data[\"t2\"] = self.resizer(\n                data[\"t2\"],\n            mode = 'nearest'\n            )\n        return data\nclass RemoveMeta(MapTransform):    \n    def __call__(\n        self, data: Mapping[Hashable, np.ndarray]\n    ) -> Mapping[Hashable, np.ndarray]:\n        data[\"t1_meta_dict\"]=0\n        data[\"t2_meta_dict\"]=0\n        data[\"t1\"]=0\n        data[\"t2\"]=0\n        return data\n\n","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:03:25.499363Z","iopub.execute_input":"2024-09-10T06:03:25.500047Z","iopub.status.idle":"2024-09-10T06:03:25.515404Z","shell.execute_reply.started":"2024-09-10T06:03:25.500022Z","shell.execute_reply":"2024-09-10T06:03:25.514600Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_transforms = Compose(\n    [\n        LoadImaged(keys=[\"t1\",\"t2\"],image_only=False),\n        EnsureChannelFirstd(keys=[\"t1\",\"t2\"]),\n        RescaleLabeld(keys=[\"t1\",\"t2\"]),\n        Spacingd(keys=[\"t1\",\"t2\"],pixdim =SPACING),\n        CustomResized(keys=[\"t1\",\"t2\"]),  #resize t2 to same size as t1\n        CustomSpatialCropd(keys=[\"t1\",\"t2\"]),\n        SpatialPadd( keys=[\"t1\",\"t2\"],spatial_size = ROI_SIZE),\n        Transposed(keys=[\"t1\",\"t2\"],indices=(0,3,1,2)),\n        ConcatItemsd(keys=[\"t1\",\"t2\"], name=\"image\", dim=1),\n        SqueezeDimd(keys=[\"image\"],dim=0),\n        NormalizeIntensityd(\n            keys=[\"image\"],nonzero=True, channel_wise=True\n        ),  \n        RemoveMeta(keys=[\"image\"]),\n        ToTensord(keys=[\"label\"]),\n        \n\n    ]\n)\n        #RandRotated(keys=[\"image\"],prob=1,range_x  = [.5,.5] ),\n        #RandGaussianNoised(keys=[\"image\"],prob=.5 ),\n        #RandShiftIntensityd(keys=[\"image\"],prob=.5,offsets = [10,20] ),\n        #RandScaleIntensityd(keys=[\"image\"],prob=.5,factors = [5,10] ),\n       #RandFlipd(keys=[\"image\"],prob=.5,spatial_axis =0 ),\n        #RandFlipd(keys=[\"image\"],prob=.5,spatial_axis =1 ),\nval_transforms = Compose(\n    [\n        LoadImaged(keys=[\"t1\",\"t2\"],image_only=False),\n        EnsureChannelFirstd(keys=[\"t1\",\"t2\"]),\n        RescaleLabeld(keys=[\"t1\",\"t2\"]),\n        Spacingd(keys=[\"t1\",\"t2\"],pixdim =SPACING),\n        CustomResized(keys=[\"t1\",\"t2\"]),  #resize t2 to same size as t1\n        CustomSpatialCropd(keys=[\"t1\",\"t2\"]),\n        SpatialPadd( keys=[\"t1\",\"t2\"],spatial_size = ROI_SIZE),\n        Transposed(keys=[\"t1\",\"t2\"],indices=(0,3,1,2)),\n        ConcatItemsd(keys=[\"t1\",\"t2\"], name=\"image\", dim=1),\n        SqueezeDimd(keys=[\"image\"],dim=0),\n        NormalizeIntensityd(\n            keys=[\"image\"],nonzero=True, channel_wise=True\n        ),  \n        RemoveMeta(keys=[\"image\"]),\n        ToTensord(keys=[\"label\"]),\n\n    ]\n)","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:03:25.516591Z","iopub.execute_input":"2024-09-10T06:03:25.516854Z","iopub.status.idle":"2024-09-10T06:03:25.537015Z","shell.execute_reply.started":"2024-09-10T06:03:25.516831Z","shell.execute_reply":"2024-09-10T06:03:25.536075Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 248\ntrain_ds = PersistentDataset( data=train_files, \n                        transform=train_transforms, \n                        cache_dir = 'cache',\n                       \n                       )\ntrain_loader = ThreadDataLoader(train_ds, batch_size=batch_size, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:03:25.538137Z","iopub.execute_input":"2024-09-10T06:03:25.538843Z","iopub.status.idle":"2024-09-10T06:03:25.556629Z","shell.execute_reply.started":"2024-09-10T06:03:25.538811Z","shell.execute_reply":"2024-09-10T06:03:25.555852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_ds = PersistentDataset(data=val_files, \n                      transform=val_transforms,\n                     \n                      cache_dir = 'cache',\n                    \n                     )\nval_loader = ThreadDataLoader(val_ds, batch_size=batch_size,shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:21:04.131599Z","iopub.execute_input":"2024-09-10T06:21:04.132581Z","iopub.status.idle":"2024-09-10T06:21:04.139809Z","shell.execute_reply.started":"2024-09-10T06:21:04.132545Z","shell.execute_reply":"2024-09-10T06:21:04.138858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_data = first(train_loader)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"s =1\nimage,label,level,filename= check_data[\"image\"][s],check_data[\"label\"],check_data[\"level\"],check_data['image'].meta[\"filename_or_obj\"][s]\nprint(f\"image shape: {image.shape},{label[s]},{level[s]},{filename}\")\nplt.figure(\"check\", (24, 12))\nplt.title(\"image\")\nplt.subplot(2,3,1)\nplt.imshow(image[0,: ,:], cmap=\"gray\")\n#plt.plot(401.6713,354.1485,\"ro\")\nplt.subplot(2,3,2)\nplt.imshow(image[1,: ,:], cmap=\"gray\")\n#plt.plot(401.6713,354.1485,\"ro\")\nplt.subplot(2,3,3)\nplt.imshow(image[2,: ,:], cmap=\"gray\")\nplt.subplot(2,3,4)\nplt.imshow(image[3,: ,:], cmap=\"gray\")\nplt.subplot(2,3,5)\nplt.imshow(image[4,: ,:], cmap=\"gray\")\nplt.subplot(2,3,6)\nplt.imshow(image[5,: ,:], cmap=\"gray\")","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:18:52.237638Z","iopub.execute_input":"2024-09-10T06:18:52.238011Z","iopub.status.idle":"2024-09-10T06:18:53.496136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_channels = ROI_SIZE[2]*2\ndrop_rate_last = 0.3\ndrop_rate = 0.\nout_dim = 3\nclass TimmModelType2(nn.Module):\n    def __init__(self, backbone, pretrained=False):\n        super(TimmModelType2, self).__init__()\n\n        self.encoder = timm.create_model(\n            backbone,\n            in_chans=input_channels,\n            num_classes=out_dim,\n            features_only=False,\n            drop_rate=drop_rate,\n            drop_path_rate=drop_rate_last,\n            pretrained=pretrained\n        )\n\n        if 'efficient' in backbone:\n            hdim = self.encoder.conv_head.out_channels\n            self.encoder.classifier = nn.Identity()\n            \n        elif 'convnext' in backbone:\n            hdim = self.encoder.head.fc.in_features\n            self.encoder.head.fc = nn.Identity()\n\n        self.lstm = nn.LSTM(hdim, 256, num_layers=2, dropout=drop_rate, bidirectional=True, batch_first=True)\n        self.head = nn.Sequential(\n            nn.Linear(512, 256),\n            nn.BatchNorm1d(256),\n            nn.Dropout(drop_rate_last),\n            nn.LeakyReLU(0.1),\n            nn.Linear(256, out_dim),\n        )\n \n\n    def forward(self, x):  # (bs, nc*7, ch, sz, sz)\n        bs = x.shape[0]\n        feat = self.encoder(x)\n        feat = feat.view(bs, -1)\n        feat1, _ = self.lstm(feat)\n        feat1 = feat1.contiguous().view(bs, 512)\n \n\n        return self.head(feat1)","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:21:13.976804Z","iopub.execute_input":"2024-09-10T06:21:13.977181Z","iopub.status.idle":"2024-09-10T06:21:13.988829Z","shell.execute_reply.started":"2024-09-10T06:21:13.977151Z","shell.execute_reply":"2024-09-10T06:21:13.987863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model1 = EfficientNetBN(\"efficientnet-b0\", pretrained=True, progress=True, spatial_dims=2, in_channels=input_channels, num_classes=3, )\nmodel2 = DenseNet(spatial_dims=2, in_channels=input_channels, out_channels=3)\nEfficientNetLSTM = TimmModelType2(\"tf_efficientnetv2_s_in21ft1k\")","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:21:15.044884Z","iopub.execute_input":"2024-09-10T06:21:15.045231Z","iopub.status.idle":"2024-09-10T06:21:15.912140Z","shell.execute_reply.started":"2024-09-10T06:21:15.045203Z","shell.execute_reply":"2024-09-10T06:21:15.911268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef validate(model):\n    model.eval()\n    num_correct,total_count = 0.0,0.0\n    label =[]\n    pred = []\n    softmax = nn.Softmax(dim=1)\n    for val_data in val_loader:\n        val_images, val_labels = val_data[\"image\"].to(device), val_data[\"label\"].to(device)\n        with torch.no_grad():\n            val_outputs = model(val_images)\n            value = torch.eq(val_outputs.argmax(dim=1), val_labels)\n            label +=list(np.array(val_labels.cpu()))\n            pred +=softmax(val_outputs.cpu()).tolist()\n            total_count += len(value)\n            num_correct += value.sum().item()\n    cur_acc = num_correct /  total_count\n    cur_auc = roc_auc_score(label,pred ,multi_class=\"ovr\")\n    return cur_acc, cur_auc\n\ndef train_model(model):\n    loss_function = torch.nn.CrossEntropyLoss(weight=torch.tensor([1.0, 2.0, 4.0]).to(device))\n    \n    if torch.cuda.is_available():\n        model.cuda()\n    optimizer = torch.optim.AdamW( model.parameters(), lr=1e-4, weight_decay=1e-5)\n    \n    val_interval = 2\n    acc = -1\n    best_metric_epoch = -1\n    epoch_loss_values = []\n    auc= -1\n    max_epochs = 30\n\n    for epoch in range(max_epochs):\n        print(\"-\" * 10)\n        print(f\"epoch {epoch + 1}/{max_epochs}\")\n        model.train()\n        epoch_loss = 0\n        step = 0\n\n        for batch_data in train_loader:\n            step += 1\n            inputs, labels = batch_data[\"image\"].to(device), batch_data[\"label\"].to(device)\n            optimizer.zero_grad()\n            outputs = model(inputs)\n            loss = loss_function(outputs, labels)\n            loss.backward()\n            optimizer.step()\n            epoch_loss += loss.item()\n            epoch_len = len(train_ds) // train_loader.batch_size\n            print(f\"{step}/{epoch_len}, train_loss: {loss.item():.4f}\")\n\n        epoch_loss /= step\n        epoch_loss_values.append(epoch_loss)\n        print(f\"epoch {epoch + 1} average loss: {epoch_loss:.4f}\")\n\n        if (epoch + 1) % val_interval == 0:\n            cur_acc, cur_auc = validate(model)\n            if cur_auc > auc:\n                auc = cur_auc\n                acc= cur_acc\n                best_metric_epoch = epoch + 1\n                torch.save(model.state_dict(), \"t1_resampled_\"+model.__class__.__name__+\".pth\")\n                print(\"saved new best metric model\")\n\n            print(f\"Current epoch: {epoch+1} current accuracy: {cur_acc:.4f} current auc: {cur_auc:.4f}\")\n            print(f\"Best accuracy: {acc:.4f} Best auc: {auc:.4f}  at epoch {best_metric_epoch}\")\n\n    return acc,auc","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:21:16.410127Z","iopub.execute_input":"2024-09-10T06:21:16.410489Z","iopub.status.idle":"2024-09-10T06:21:16.425844Z","shell.execute_reply.started":"2024-09-10T06:21:16.410459Z","shell.execute_reply":"2024-09-10T06:21:16.424837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"acc,auc = train_model(EfficientNetLSTM) ","metadata":{"execution":{"iopub.status.busy":"2024-09-10T06:21:17.435414Z","iopub.execute_input":"2024-09-10T06:21:17.436436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds = CacheDataset(data=test_files, \n                      transform=val_transforms,\n                      num_workers=-1,\n                     )\ntest_loader = DataLoader(test_ds, batch_size=batch_size,shuffle=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = TimmModelType2(\"tf_efficientnetv2_s_in21ft1k\").cuda()\nmodel.load_state_dict(torch.load(\"t1_resampled_\"+model.__class__.__name__+\".pth\"))\n\nlabel =  []\npred = []\nsoftmax = nn.Softmax(dim=1)\nfor test_data in test_loader:\n    test_images, test_labels = test_data[\"image\"].to(device), test_data[\"label\"].to(device)\n    with torch.no_grad():\n        test_outputs = model(test_images)\n   \n        label +=list(test_labels.cpu().tolist())\n        pred +=softmax(test_outputs.cpu()).tolist()\n\nauc = roc_auc_score(label, pred,multi_class=\"ovr\",)\n\nmetric = np.equal(np.array(pred).argmax(axis=1),label).sum() / len(pred)\nprint(metric,auc)\ncm = confusion_matrix(label,np.array(pred).argmax(axis=1))\ndisp = ConfusionMatrixDisplay(confusion_matrix=cm,display_labels = [0, 1,2])\ndisp.plot()\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}