{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"},{"sourceId":213819748,"sourceType":"kernelVersion"}],"dockerImageVersionId":30823,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport seaborn as sns\n\nimport matplotlib.pyplot as plt\nimport os\nimport time\nimport numpy as np\nimport glob\nimport json\nimport collections\nimport torch\nimport torch.nn as nn\n\nimport pydicom as dicom\nimport matplotlib.patches as patches\n\nfrom matplotlib import animation, rc\nimport pandas as pd\n\nimport pydicom as dicom # dicom\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:42.295365Z","iopub.execute_input":"2024-12-19T13:31:42.295690Z","iopub.status.idle":"2024-12-19T13:31:42.301423Z","shell.execute_reply.started":"2024-12-19T13:31:42.295642Z","shell.execute_reply":"2024-12-19T13:31:42.300439Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# read data\ntrain_path = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/'\n\ntrain  = pd.read_csv(train_path + 'train.csv')\nlabel = pd.read_csv(train_path + 'train_label_coordinates.csv')\ntrain_desc  = pd.read_csv(train_path + 'train_series_descriptions.csv')\ntest_desc   = pd.read_csv(train_path + 'test_series_descriptions.csv')\nsub         = pd.read_csv(train_path + 'sample_submission.csv')\nlen(test_desc) #number of test_description.csv rows ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:42.302692Z","iopub.execute_input":"2024-12-19T13:31:42.302899Z","iopub.status.idle":"2024-12-19T13:31:42.389040Z","shell.execute_reply.started":"2024-12-19T13:31:42.302880Z","shell.execute_reply":"2024-12-19T13:31:42.388100Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_desc.head(5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:42.391096Z","iopub.execute_input":"2024-12-19T13:31:42.391325Z","iopub.status.idle":"2024-12-19T13:31:42.398637Z","shell.execute_reply.started":"2024-12-19T13:31:42.391304Z","shell.execute_reply":"2024-12-19T13:31:42.397683Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Function to generate image paths based on directory structure\ndef generate_image_paths(df, data_dir):\n    image_paths = []\n    for study_id, series_id in zip(df['study_id'], df['series_id']):\n        study_dir = os.path.join(data_dir, str(study_id))\n        series_dir = os.path.join(study_dir, str(series_id))\n        images = os.listdir(series_dir)\n        image_paths.extend([os.path.join(series_dir, img) for img in images])\n    return image_paths\n\ntest_image_paths = generate_image_paths(test_desc, f'{train_path}/test_images')\nfrom concurrent.futures import ThreadPoolExecutor\ndef load_dicom(path):\n    dicom = pydicom.dcmread(path)\n    data = dicom.pixel_array\n    data = data - np.min(data)\n    if np.max(data) != 0:\n        data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n    return data\nfrom concurrent.futures import ThreadPoolExecutor\ndef load_all_dicom(paths):\n    with ThreadPoolExecutor() as executor:\n        images = list(executor.map(load_dicom, paths))\n    return images","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:42.399688Z","iopub.execute_input":"2024-12-19T13:31:42.399903Z","iopub.status.idle":"2024-12-19T13:31:42.415377Z","shell.execute_reply.started":"2024-12-19T13:31:42.399884Z","shell.execute_reply":"2024-12-19T13:31:42.414636Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define the base path for test images\nbase_path = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/test_images/'\n\n# Function to get image paths for a series\ndef get_image_paths(row):\n    series_path = os.path.join(base_path, str(row['study_id']), str(row['series_id']))\n    if os.path.exists(series_path):\n        return [os.path.join(series_path, f) for f in os.listdir(series_path) if os.path.isfile(os.path.join(series_path, f))]\n    return []\n\n# Mapping of series_description to conditions\ncondition_mapping = {\n    'Sagittal T1': {'left': 'left_neural_foraminal_narrowing', 'right': 'right_neural_foraminal_narrowing'},\n    'Axial T2': {'left': 'left_subarticular_stenosis', 'right': 'right_subarticular_stenosis'},\n    'Sagittal T2/STIR': 'spinal_canal_stenosis'\n}\n\n# Create a list to store the expanded rows\nexpanded_rows = []\n\"\"\"\n# Expand the dataframe by adding new rows for each file path\nfor index, row in test_desc.iterrows():\n    image_paths = get_image_paths(row)\n    conditions = condition_mapping.get(row['series_description'], {})\n    if isinstance(conditions, str):  # Single condition\n        conditions = {'left': conditions, 'right': conditions}\n    for side, condition in conditions.items():\n        for image_path in image_paths:\n            expanded_rows.append({\n                'study_id': row['study_id'],\n                'series_id': row['series_id'],\n                'series_description': row['series_description'],\n                'image_path': image_path,\n                'condition': condition,\n                'row_id': f\"{row['study_id']}_{condition}\"\n            })\n\n# Create a new dataframe from the expanded rows\nexpanded_test_desc = pd.DataFrame(expanded_rows)\n\"\"\"\nfor index, row in test_desc.iterrows():\n    image_paths = get_image_paths(row)\n    loaded_images = load_all_dicom(image_paths)  # Paralel DICOM yükleme\n    conditions = condition_mapping.get(row['series_description'], {})\n    if isinstance(conditions, str):  # Single condition\n        conditions = {'left': conditions, 'right': conditions}\n    for side, condition in conditions.items():\n        for image_path, dicom_image in zip(image_paths, loaded_images):\n            expanded_rows.append({\n                'study_id': row['study_id'],\n                'series_id': row['series_id'],\n                'series_description': row['series_description'],\n                'image_path': image_path,\n                'dicom_image': dicom_image,  # Yüklenmiş görüntü\n                'condition': condition,\n                'row_id': f\"{row['study_id']}_{condition}\"\n            })\n\n# DataFrame oluşturma\nexpanded_test_desc = pd.DataFrame(expanded_rows)\n# Display the resulting dataframe\nexpanded_test_desc.head(5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:42.416317Z","iopub.execute_input":"2024-12-19T13:31:42.416609Z","iopub.status.idle":"2024-12-19T13:31:44.013074Z","shell.execute_reply.started":"2024-12-19T13:31:42.416577Z","shell.execute_reply":"2024-12-19T13:31:44.012278Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_data = expanded_test_desc","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:44.013965Z","iopub.execute_input":"2024-12-19T13:31:44.014285Z","iopub.status.idle":"2024-12-19T13:31:44.017451Z","shell.execute_reply.started":"2024-12-19T13:31:44.014247Z","shell.execute_reply":"2024-12-19T13:31:44.016746Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# Define a function to check if a path exists\ndef check_exists(path):\n    return os.path.exists(path)\n\n# Define a function to check if a study ID directory exists\ndef check_study_id(row):\n    study_id = row['study_id']\n    path = f'{train_path}/train_images/{study_id}'\n    return check_exists(path)\n\n# Define a function to check if a series ID directory exists\ndef check_series_id(row):\n    study_id = row['study_id']\n    series_id = row['series_id']\n    path = f'{train_path}/train_images/{study_id}/{series_id}'\n    return check_exists(path)\n\n# Define a function to check if an image file exists\ndef check_image_exists(row):\n    image_path = row['image_path']\n    return check_exists(image_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:44.019265Z","iopub.execute_input":"2024-12-19T13:31:44.019526Z","iopub.status.idle":"2024-12-19T13:31:44.033441Z","shell.execute_reply.started":"2024-12-19T13:31:44.019506Z","shell.execute_reply":"2024-12-19T13:31:44.032743Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_dicom(path):\n    dicom = pydicom.dcmread(path)\n    data = dicom.pixel_array\n    data = data - np.min(data)\n    if np.max(data) != 0:\n        data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n    return data\n\nfrom concurrent.futures import ThreadPoolExecutor\n\ndef load_all_dicom(paths):\n    with ThreadPoolExecutor() as executor:\n        images = list(executor.map(load_dicom, paths))\n    return images\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:44.034888Z","iopub.execute_input":"2024-12-19T13:31:44.035128Z","iopub.status.idle":"2024-12-19T13:31:44.051631Z","shell.execute_reply.started":"2024-12-19T13:31:44.035108Z","shell.execute_reply":"2024-12-19T13:31:44.050912Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.models as models\nfrom torchvision import transforms\nfrom torch.utils.data import DataLoader\nfrom sklearn.model_selection import train_test_split\nimport pandas as pd\nfrom tqdm import tqdm\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:44.052429Z","iopub.execute_input":"2024-12-19T13:31:44.052715Z","iopub.status.idle":"2024-12-19T13:31:44.065916Z","shell.execute_reply.started":"2024-12-19T13:31:44.052687Z","shell.execute_reply":"2024-12-19T13:31:44.065316Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"expanded_test_desc","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:44.066557Z","iopub.execute_input":"2024-12-19T13:31:44.066770Z","iopub.status.idle":"2024-12-19T13:31:44.630609Z","shell.execute_reply.started":"2024-12-19T13:31:44.066752Z","shell.execute_reply":"2024-12-19T13:31:44.629596Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"levels = ['l1_l2', 'l2_l3', 'l3_l4', 'l4_l5', 'l5_s1']\n\n# Function to update row_id with levels\ndef update_row_id(row, levels):\n    level = levels[row.name % len(levels)]\n    return f\"{row['study_id']}_{row['condition']}_{level}\"\n\n# Update row_id in expanded_test_desc to include levels\nexpanded_test_desc['row_id'] = expanded_test_desc.apply(lambda row: update_row_id(row, levels), axis=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:44.631539Z","iopub.execute_input":"2024-12-19T13:31:44.632017Z","iopub.status.idle":"2024-12-19T13:31:44.639458Z","shell.execute_reply.started":"2024-12-19T13:31:44.631984Z","shell.execute_reply":"2024-12-19T13:31:44.637931Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"expanded_test_desc.head(2)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:44.640418Z","iopub.execute_input":"2024-12-19T13:31:44.640633Z","iopub.status.idle":"2024-12-19T13:31:44.771952Z","shell.execute_reply.started":"2024-12-19T13:31:44.640613Z","shell.execute_reply":"2024-12-19T13:31:44.771079Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.transforms as transforms\nimport torch\nimport torch.optim.lr_scheduler as lr_scheduler\nfrom tqdm import tqdm\n# Define a custom test dataset class\nclass TestDataset(Dataset):\n    def __init__(self, dataframe, transform=None):\n        self.dataframe = dataframe\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.dataframe)\n\n    def __getitem__(self, index):\n        image_path = self.dataframe['image_path'][index]\n        image = load_dicom(image_path)  # Define this function to load your DICOM images\n        if self.transform:\n            image = self.transform(image)\n        return image\n\n# Define the transforms\ntransform = transforms.Compose([\n    transforms.ToPILImage(),\n    transforms.Resize((224, 224)),\n    transforms.Grayscale(num_output_channels=3),\n    transforms.ToTensor(),\n])\n\n# Create a test dataset and dataloader\ntest_dataset = TestDataset(expanded_test_desc, transform)\ntestloader = DataLoader(test_dataset, batch_size=16, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:44.774479Z","iopub.execute_input":"2024-12-19T13:31:44.774731Z","iopub.status.idle":"2024-12-19T13:31:44.781505Z","shell.execute_reply.started":"2024-12-19T13:31:44.774710Z","shell.execute_reply":"2024-12-19T13:31:44.780618Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for image in testloader:\n    print(image.shape)\n    break","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:44.782597Z","iopub.execute_input":"2024-12-19T13:31:44.782843Z","iopub.status.idle":"2024-12-19T13:31:45.085787Z","shell.execute_reply.started":"2024-12-19T13:31:44.782812Z","shell.execute_reply":"2024-12-19T13:31:45.084863Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom torchvision import models\nimport torch.nn as nn\n\nclass CustomResNet50(nn.Module):\n    def __init__(self, num_classes=3, pretrained_weights=None):\n        super(CustomResNet50, self).__init__()\n        \n        # Yeni weights parametresini kullanarak ResNet50'yi başlatıyoruz\n        self.model = models.resnet50(weights=None).to(device)\n        \n        # Eğer özel bir ağırlık dosyası varsa yükle\n        if pretrained_weights:\n            self.model.load_state_dict(torch.load(pretrained_weights, map_location=device), strict=False)\n                \n\n        \n        # Son katmanı sınıf sayısına göre değiştir\n        num_ftrs = self.model.fc.in_features\n        self.model.fc = nn.Linear(num_ftrs, num_classes)\n\n    def forward(self, x):\n        return self.model(x)\n\n\"\"\"!!!!!!!!!!!!!!!!!!!!!!!!BURADA YOLLARI OGRENMEN GEREK SABAH DUZELTCEKSIN!!!!!!!!!!!!!!!!!!!!!!!!\"\"\"\nimport torch\n\n# Function to get the model based on series_description and load pretrained weights\ndef get_model(series_description, weights_paths):\n    model_name = series_description\n    if model_name in weights_paths:\n        model = CustomResNet50(num_classes=3, pretrained_weights=weights_paths[model_name]).to(device)\n        model.eval()  # Modeli değerlendirme moduna al\n        return model\n    return None\n\n\n\"\"\"\n# Function to make predictions on the test data\ndef predict_test_data(testloader, expanded_test_desc, weights_paths):\n    predictions = []\n    normal_mild_probs = []\n    moderate_probs = []\n    severe_probs = []\n    \n    for idx, images in enumerate(tqdm(testloader)):\n        images = images.to(device)\n        series_description = expanded_test_desc.iloc[idx]['series_description']\n        model = get_model(series_description, weights_paths)\n        \n        if model:\n            with torch.no_grad():\n                outputs = model(images)\n                probs = torch.softmax(outputs, dim=1).squeeze(0)\n                normal_mild_probs.append(probs[0].item())\n                moderate_probs.append(probs[1].item())\n                severe_probs.append(probs[2].item())\n                predictions.append(probs)\n        else:\n            normal_mild_probs.append(None)\n            moderate_probs.append(None)\n            severe_probs.append(None)\n            predictions.append(None)\n    \n    return normal_mild_probs, moderate_probs, severe_probs, predictions\n    \"\"\"\ndef predict_test_data(testloader, expanded_test_desc, weights_paths):\n    predictions = []\n    normal_mild_probs = []\n    moderate_probs = []\n    severe_probs = []\n    test_predictions = []  # Eklenen liste\n    \n    for idx, images in enumerate(tqdm(testloader)):\n        images = images.to(device)\n        series_description = expanded_test_desc.iloc[idx]['series_description']\n        model = get_model(series_description, weights_paths)\n        \n        if model:\n            with torch.no_grad():\n                outputs = model(images)\n                probs = torch.softmax(outputs, dim=1)\n                for prob in probs:  # Her batch içindeki her görüntü için ayrı ayrı ele al\n                    normal_mild_probs.append(prob[0].item())\n                    moderate_probs.append(prob[1].item())\n                    severe_probs.append(prob[2].item())\n                    test_predictions.append(prob.cpu().numpy())  # NumPy formatında sakla\n        else:\n            for _ in range(len(images)):  # Batch boyutuna göre None ekle\n                normal_mild_probs.append(None)\n                moderate_probs.append(None)\n                severe_probs.append(None)\n                test_predictions.append(None)\n    \n    return normal_mild_probs, moderate_probs, severe_probs, test_predictions\n\n\n\n\nweights_paths = {\n    'Sagittal T1': '/kaggle/input/fork-of-fixed-train-with-severe-focused-augmentati/best_model_Sagittal_T1.pth',\n    'Axial T2': '/kaggle/input/fork-of-fixed-train-with-severe-focused-augmentati/best_model_Axial_T2.pth',\n    'Sagittal T2/STIR': '/kaggle/input/fork-of-fixed-train-with-severe-focused-augmentati/best_model_Sagittal_T2_STIR.pth'\n}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:45.086741Z","iopub.execute_input":"2024-12-19T13:31:45.087025Z","iopub.status.idle":"2024-12-19T13:31:45.096858Z","shell.execute_reply.started":"2024-12-19T13:31:45.086996Z","shell.execute_reply":"2024-12-19T13:31:45.096007Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Make predictions on the test data\nnormal_mild_probs, moderate_probs, severe_probs, test_predictions = predict_test_data(testloader, expanded_test_desc, weights_paths)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:45.097557Z","iopub.execute_input":"2024-12-19T13:31:45.097803Z","iopub.status.idle":"2024-12-19T13:31:54.194735Z","shell.execute_reply.started":"2024-12-19T13:31:45.097783Z","shell.execute_reply":"2024-12-19T13:31:54.193989Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_predictions[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:54.195512Z","iopub.execute_input":"2024-12-19T13:31:54.195773Z","iopub.status.idle":"2024-12-19T13:31:54.201001Z","shell.execute_reply.started":"2024-12-19T13:31:54.195751Z","shell.execute_reply":"2024-12-19T13:31:54.200108Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Add predictions and probabilities to the test DataFrame\nexpanded_test_desc['normal_mild'] = normal_mild_probs\nexpanded_test_desc['moderate'] = moderate_probs\nexpanded_test_desc['severe'] = severe_probs","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:54.201844Z","iopub.execute_input":"2024-12-19T13:31:54.202106Z","iopub.status.idle":"2024-12-19T13:31:54.216440Z","shell.execute_reply.started":"2024-12-19T13:31:54.202085Z","shell.execute_reply":"2024-12-19T13:31:54.215588Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = expanded_test_desc[[\"row_id\",\"normal_mild\",\"moderate\",\"severe\"]]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:54.217350Z","iopub.execute_input":"2024-12-19T13:31:54.217627Z","iopub.status.idle":"2024-12-19T13:31:54.231106Z","shell.execute_reply.started":"2024-12-19T13:31:54.217597Z","shell.execute_reply":"2024-12-19T13:31:54.230196Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Group by 'row_id' and sum the values\ngrouped_submission = submission.groupby('row_id').max().reset_index()\n\n# Normalize the columns\ngrouped_submission[['normal_mild', 'moderate', 'severe']] = grouped_submission[['normal_mild', 'moderate', 'severe']].div(grouped_submission[['normal_mild', 'moderate', 'severe']].sum(axis=1), axis=0)\n\n# Check the first 3 rows\ngrouped_submission","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:54.232149Z","iopub.execute_input":"2024-12-19T13:31:54.232438Z","iopub.status.idle":"2024-12-19T13:31:54.255833Z","shell.execute_reply.started":"2024-12-19T13:31:54.232409Z","shell.execute_reply":"2024-12-19T13:31:54.255071Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"len(grouped_submission)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:54.256474Z","iopub.execute_input":"2024-12-19T13:31:54.256652Z","iopub.status.idle":"2024-12-19T13:31:54.272810Z","shell.execute_reply.started":"2024-12-19T13:31:54.256635Z","shell.execute_reply":"2024-12-19T13:31:54.272042Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sub[['normal_mild', 'moderate', 'severe']] = grouped_submission[['normal_mild', 'moderate', 'severe']]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:54.273497Z","iopub.execute_input":"2024-12-19T13:31:54.273719Z","iopub.status.idle":"2024-12-19T13:31:54.287520Z","shell.execute_reply.started":"2024-12-19T13:31:54.273691Z","shell.execute_reply":"2024-12-19T13:31:54.286735Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# Save the DataFrame to \"submission.csv\" in the desired directory\nsub.to_csv(\"/kaggle/working/submission.csv\", index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:54.288338Z","iopub.execute_input":"2024-12-19T13:31:54.288643Z","iopub.status.idle":"2024-12-19T13:31:54.302655Z","shell.execute_reply.started":"2024-12-19T13:31:54.288613Z","shell.execute_reply":"2024-12-19T13:31:54.302031Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sub.head(5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-19T13:31:54.303335Z","iopub.execute_input":"2024-12-19T13:31:54.303516Z","iopub.status.idle":"2024-12-19T13:31:54.319445Z","shell.execute_reply.started":"2024-12-19T13:31:54.303500Z","shell.execute_reply":"2024-12-19T13:31:54.318715Z"}},"outputs":[],"execution_count":null}]}