{"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":"# Training Data Cleaning for [BirdCLEF2023](https://www.kaggle.com/competitions/birdclef-2023)\n## Introduction\nThis notebook looks at the data from BirdCLEF 2021, 2022 and 2023.  Produces two outputs\n\n- A csv file with the 2023 dataset reduced to 'primary_label', 'secondary_labels', 'type', 'filename','filepath'.  File path is relative to the kaggle input folder.\n- A csv file in the same format, with rows containing 100% of the 2023 data, plus training samples from 22 & 21, without any duplicates.\n\nAll the file names in both csv files are now unique, and in the same format. I have removed 6,686 cases where there was overlap between competitions, plus a remaining 7 cases where the same file name existed in more than one class folder.\n\n## Usage\nYou could link the datasets from all three years, and use these two CSV files to create your training and validation splits, for pretraining on all the data and finetuning on the 2023 dataset, all in the same format.\n\n## Dataset\nI have uploaded the CSV files to a dataset [here](https://www.kaggle.com/datasets/ollypowell/cleaned-training-labels-21-23-for-birdclef2023)","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport librosa\nfrom pathlib import Path\nfrom collections import Counter\nfrom IPython.display import Audio","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-03-27T01:35:02.093560Z","iopub.execute_input":"2023-03-27T01:35:02.094209Z","iopub.status.idle":"2023-03-27T01:35:02.098683Z","shell.execute_reply.started":"2023-03-27T01:35:02.094172Z","shell.execute_reply":"2023-03-27T01:35:02.097635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# setup file paths\ndata_folder = Path('/kaggle/input')  #modify to suit\nout_folder = Path('/kaggle/working')\n\ntrain_21 = data_folder / 'birdclef-2021' / 'train_short_audio'\ntrain_22 =  data_folder / 'birdclef-2022' / 'train_audio'\ntrain_23 = data_folder / 'birdclef-2023' / 'train_audio'\n\ntrain_21_csv = data_folder / 'birdclef-2021' / 'train_metadata.csv'\ntrain_22_csv = data_folder / 'birdclef-2022' / 'train_metadata.csv'\ntrain_23_csv = data_folder / 'birdclef-2023' / 'train_metadata.csv'\n\nin_csv_fields = ['primary_label', 'secondary_labels', 'type', 'filename']\ncsv_datatypes = {'primary_label': str, 'secondary_labels': str, 'type': str, 'filename': str}\n\nout_csv_all_pth = out_folder / 'train_21_22_23.csv'\nout_csv_23_pth = out_folder / 'train_23.csv'","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:35:02.100684Z","iopub.execute_input":"2023-03-27T01:35:02.101000Z","iopub.status.idle":"2023-03-27T01:35:02.117550Z","shell.execute_reply.started":"2023-03-27T01:35:02.100971Z","shell.execute_reply":"2023-03-27T01:35:02.116100Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def play_audio(file_path):\n    audio_abe, sr_abe = librosa.load(file_path)\n    return Audio(data=audio_abe, rate=sr_abe)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:35:02.120240Z","iopub.execute_input":"2023-03-27T01:35:02.121524Z","iopub.status.idle":"2023-03-27T01:35:02.128000Z","shell.execute_reply.started":"2023-03-27T01:35:02.121470Z","shell.execute_reply":"2023-03-27T01:35:02.126503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sfiles_23 = {f:str(f.name) for f in Path(train_23).rglob('*.ogg')}\nsfiles_22 = {f:str(f.name) for f in Path(train_22).rglob('*.ogg')}\nsfiles_21 = {f:str(f.name) for f in Path(train_21).rglob('*.ogg')}\n\nall_sfiles = {**sfiles_23, **sfiles_22, **sfiles_21}\n\nunique_names =  set(all_sfiles.values())\nunique_names_w_folder = set([str(k.parent.name) + '/' + str(k.name) for (k,v) in all_sfiles.items()])\nlen_all_sfiles = len(all_sfiles)\nprint(f'All file names by path: {len_all_sfiles}')\nprint(f'Unique file names including folder name: {len(unique_names_w_folder)}')\nprint(f'Unique file names {len(unique_names)}')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:35:02.129477Z","iopub.execute_input":"2023-03-27T01:35:02.130496Z","iopub.status.idle":"2023-03-27T01:35:04.586674Z","shell.execute_reply.started":"2023-03-27T01:35:02.130449Z","shell.execute_reply":"2023-03-27T01:35:04.585522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"It would be good to varify that the files are genuinely different birds, not just different spellings of the folders, or files in the wrong folders.","metadata":{}},{"cell_type":"code","source":"item_counts = Counter(all_sfiles.values()) \nduplicates = list([item for item in item_counts if item_counts[item]>1])\nprint(f'Number of duplicate file names found: {len(duplicates)}')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:35:04.588998Z","iopub.execute_input":"2023-03-27T01:35:04.589340Z","iopub.status.idle":"2023-03-27T01:35:04.633729Z","shell.execute_reply.started":"2023-03-27T01:35:04.589308Z","shell.execute_reply":"2023-03-27T01:35:04.632584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now I'm going to examine the folder names for each of these duplicates","metadata":{}},{"cell_type":"code","source":"dupes_dict = {}\nfor dup in duplicates:\n    #find matching file paths and put them in a dict\n    dupes_dict[dup] = [str(k.parent.name) + '/' + str(k.name) for (k,v) in all_sfiles.items() if v == dup]\ndict(list(dupes_dict.items())[0: 6])","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:35:04.637259Z","iopub.execute_input":"2023-03-27T01:35:04.637592Z","iopub.status.idle":"2023-03-27T01:36:08.812296Z","shell.execute_reply.started":"2023-03-27T01:35:04.637561Z","shell.execute_reply":"2023-03-27T01:36:08.811041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This is as expected, most duplicates have the same folder name, they are just overlap between different competitions.  But the first on the list does not, and there are potentially 5 others like this as it was earier noted there are 5 more unique folder-name combinations than just unique names.  I'm going to sort through the duplicates to find these examples.","metadata":{}},{"cell_type":"code","source":"matches = {k:v for (k,v) in dupes_dict.items() if len(set(v)) > 1}\nmatches","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:08.813956Z","iopub.execute_input":"2023-03-27T01:36:08.814288Z","iopub.status.idle":"2023-03-27T01:36:08.826066Z","shell.execute_reply.started":"2023-03-27T01:36:08.814257Z","shell.execute_reply":"2023-03-27T01:36:08.824745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"11 Files found.  Now all that's left to do is listen to see if they are actually different birds, or just labelling errors","metadata":{}},{"cell_type":"code","source":"matches_dict = {}\nfor key in matches.keys():\n    matches_dict[key] = [k for (k,v) in all_sfiles.items() if v == key]\nmatches_dict","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:08.827802Z","iopub.execute_input":"2023-03-27T01:36:08.828877Z","iopub.status.idle":"2023-03-27T01:36:08.889578Z","shell.execute_reply.started":"2023-03-27T01:36:08.828829Z","shell.execute_reply":"2023-03-27T01:36:08.888441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Going through the four pairs and one triple, and checking if they are actually different files.","metadata":{}},{"cell_type":"code","source":"# Checking XC316684.ogg gnbcam2\nplay_audio('/kaggle/input/birdclef-2021/train_short_audio/mallar3/XC501149.ogg')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:08.890877Z","iopub.execute_input":"2023-03-27T01:36:08.891880Z","iopub.status.idle":"2023-03-27T01:36:08.924984Z","shell.execute_reply.started":"2023-03-27T01:36:08.891824Z","shell.execute_reply":"2023-03-27T01:36:08.923928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Checking XC316684.ogg cibwar1\nplay_audio('/kaggle/input/birdclef-2023/train_audio/cibwar1/XC316684.ogg')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:08.926487Z","iopub.execute_input":"2023-03-27T01:36:08.926893Z","iopub.status.idle":"2023-03-27T01:36:08.985460Z","shell.execute_reply.started":"2023-03-27T01:36:08.926855Z","shell.execute_reply":"2023-03-27T01:36:08.984218Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"They are definately the same file.  Sounds like there are two types of birds present.","metadata":{}},{"cell_type":"code","source":"# Checking XC514027.ogg gnbcam2\nplay_audio('/kaggle/input/birdclef-2023/train_audio/laudov1/XC514027.ogg')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:08.990802Z","iopub.execute_input":"2023-03-27T01:36:08.991227Z","iopub.status.idle":"2023-03-27T01:36:09.146548Z","shell.execute_reply.started":"2023-03-27T01:36:08.991189Z","shell.execute_reply":"2023-03-27T01:36:09.145306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Checking XC514027.ogg eucdov\nplay_audio('/kaggle/input/birdclef-2021/train_short_audio/eucdov/XC514027.ogg')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:09.148137Z","iopub.execute_input":"2023-03-27T01:36:09.148592Z","iopub.status.idle":"2023-03-27T01:36:09.311571Z","shell.execute_reply.started":"2023-03-27T01:36:09.148555Z","shell.execute_reply":"2023-03-27T01:36:09.310699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"They are definately the same file. There are at least two different birds present.","metadata":{}},{"cell_type":"code","source":"# Checking  XC294370.ogg brant\nplay_audio('/kaggle/input/birdclef-2022/train_audio/brant/XC294370.ogg')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:09.312654Z","iopub.execute_input":"2023-03-27T01:36:09.312993Z","iopub.status.idle":"2023-03-27T01:36:09.334350Z","shell.execute_reply.started":"2023-03-27T01:36:09.312952Z","shell.execute_reply":"2023-03-27T01:36:09.333199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Checking  XC294370.ogg gadwal\nplay_audio('/kaggle/input/birdclef-2022/train_audio/gadwal/XC294370.ogg')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:09.335809Z","iopub.execute_input":"2023-03-27T01:36:09.336144Z","iopub.status.idle":"2023-03-27T01:36:09.357348Z","shell.execute_reply.started":"2023-03-27T01:36:09.336111Z","shell.execute_reply":"2023-03-27T01:36:09.356295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I could only hear one bird there, but it's a really short clip","metadata":{}},{"cell_type":"code","source":"# XC477595.ogg  norcar\nplay_audio('/kaggle/input/birdclef-2022/train_audio/norcar/XC477595.ogg')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:09.358643Z","iopub.execute_input":"2023-03-27T01:36:09.359629Z","iopub.status.idle":"2023-03-27T01:36:09.529866Z","shell.execute_reply.started":"2023-03-27T01:36:09.359573Z","shell.execute_reply":"2023-03-27T01:36:09.527624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# XC477595.ogg\nplay_audio('/kaggle/input/birdclef-2021/train_short_audio/carwre/XC477595.ogg')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:09.531506Z","iopub.execute_input":"2023-03-27T01:36:09.531899Z","iopub.status.idle":"2023-03-27T01:36:09.714849Z","shell.execute_reply.started":"2023-03-27T01:36:09.531864Z","shell.execute_reply":"2023-03-27T01:36:09.713483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The same file, and definately at least two birds present.","metadata":{}},{"cell_type":"code","source":"# XC501149.ogg  gnwtea\nplay_audio('/kaggle/input/birdclef-2022/train_audio/gnwtea/XC501149.ogg')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:09.716870Z","iopub.execute_input":"2023-03-27T01:36:09.717790Z","iopub.status.idle":"2023-03-27T01:36:09.772221Z","shell.execute_reply.started":"2023-03-27T01:36:09.717738Z","shell.execute_reply":"2023-03-27T01:36:09.771144Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#XC501149.ogg mallar3\nplay_audio('/kaggle/input/birdclef-2021/train_short_audio/mallar3/XC501149.ogg')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:09.773652Z","iopub.execute_input":"2023-03-27T01:36:09.774062Z","iopub.status.idle":"2023-03-27T01:36:09.806687Z","shell.execute_reply.started":"2023-03-27T01:36:09.774030Z","shell.execute_reply":"2023-03-27T01:36:09.805381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Not sure about that one, difinately the same file, not sure if there was more than one type of bird.\n\nSo in summary 3/5 of these pairs had two birds at least present, so they could be correct labels.  The other two I'm not sure about.  However only three files: cibwar1/XC316684.ogg, gnbcam2/XC316684.ogg, and eucdov/XC514027.ogg are in this years competition, and they all have more than one bird present, so could their classification could be correct. The rest could only be useful for pre-training, so they won't make much difference anyway.  I'm going to drop everything except cibwar1/XC316684.ogg, gnbcam2/XC316684.ogg & eucdov/XC514027.ogg","metadata":{}},{"cell_type":"code","source":"keep_files = ['/kaggle/input/birdclef-2023/train_audio/cibwar1/XC316684.ogg', \n              '/kaggle/input/birdclef-2023/train_audio/gnbcam2/XC316684.ogg',\n              '/kaggle/input/birdclef-2021/train_short_audio/eucdov/XC514027.ogg']\ndrop_files =  [item for sublist in matches_dict.values() for item in sublist if str(item) not in keep_files]\nlen(drop_files)  ","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:09.808137Z","iopub.execute_input":"2023-03-27T01:36:09.808449Z","iopub.status.idle":"2023-03-27T01:36:09.817346Z","shell.execute_reply.started":"2023-03-27T01:36:09.808418Z","shell.execute_reply":"2023-03-27T01:36:09.816090Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"With the duplicates understood, I'm going to re-build the combined dictionary from the three years, without duplicates","metadata":{}},{"cell_type":"code","source":"sfiles_22 = {k:v for (k,v) in sfiles_22.items() if v not in sfiles_23.values()}\nvals_22_23 = list(sfiles_23.values()) + list(sfiles_22.values())\nsfiles_21 = {k:v for (k,v) in sfiles_21.items() if v not in vals_22_23}\n\nall_sfiles = {**sfiles_23, **sfiles_22, **sfiles_21}\nall_sf_len = len(all_sfiles)\nprint(f'{all_sf_len} unique file names in the dict from 21, 22, 23')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:09.818952Z","iopub.execute_input":"2023-03-27T01:36:09.819345Z","iopub.status.idle":"2023-03-27T01:36:51.202884Z","shell.execute_reply.started":"2023-03-27T01:36:09.819308Z","shell.execute_reply":"2023-03-27T01:36:51.201666Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# And drop those files from 22 & 21 that might be mislabeled, or have two birds\nfor key in drop_files:\n    all_sfiles.pop(key, None)\n    \nprint(f'{len(all_sfiles)} unique file names in the dict from 21, 22, 23')\nprint(f'{all_sf_len - len(all_sfiles)} items were removed because they were the same file name in different class folders')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:51.204394Z","iopub.execute_input":"2023-03-27T01:36:51.204940Z","iopub.status.idle":"2023-03-27T01:36:51.211532Z","shell.execute_reply.started":"2023-03-27T01:36:51.204894Z","shell.execute_reply":"2023-03-27T01:36:51.210334Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"So now I have two cleaner dictionaries in the form {(file_path: file_name)}  `sfiles_23` with the 2023 data and all_sfiles with unique data from 21, 22 & 23.","metadata":{}},{"cell_type":"code","source":"df_23 = pd.read_csv(train_23_csv,  usecols=in_csv_fields, dtype=csv_datatypes, index_col=None)\ndf_22 = pd.read_csv(train_22_csv,  usecols=in_csv_fields, dtype=csv_datatypes, index_col=None)\ndf_21 = pd.read_csv(train_21_csv,  usecols=in_csv_fields, dtype=csv_datatypes, index_col=None)\n\nprint(f'Dataframe lengths: {[len(df_23), len(df_22), len(df_21)]}')\nprint(f'Total number of sound files in the three datasets: {len_all_sfiles}')\nprint(f'Total rows (should match the number of files): {len(df_23) + len(df_22) +len(df_21)}')\ndf_23.head(3)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:51.213038Z","iopub.execute_input":"2023-03-27T01:36:51.213922Z","iopub.status.idle":"2023-03-27T01:36:51.524232Z","shell.execute_reply.started":"2023-03-27T01:36:51.213875Z","shell.execute_reply":"2023-03-27T01:36:51.522891Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_22.head(3)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:51.525686Z","iopub.execute_input":"2023-03-27T01:36:51.526120Z","iopub.status.idle":"2023-03-27T01:36:51.537989Z","shell.execute_reply.started":"2023-03-27T01:36:51.526074Z","shell.execute_reply":"2023-03-27T01:36:51.536542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_21.head(3)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:51.539538Z","iopub.execute_input":"2023-03-27T01:36:51.540305Z","iopub.status.idle":"2023-03-27T01:36:51.554898Z","shell.execute_reply.started":"2023-03-27T01:36:51.540259Z","shell.execute_reply":"2023-03-27T01:36:51.553539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The dataframes are consistant, except for the filenames of 2021 which does not include the parent folder, and for matching all three years data I'll need the full file path.  I'm going to a new column for the full file path, then strip the parent from the filename column in 22 and 23.","metadata":{}},{"cell_type":"code","source":"def build_path(bird,fn): \n    return str(train_21) + '/' + bird + '/' + fn\n\ndf_23['filepath'] = df_23['filename'].apply(lambda x: str(train_23) + '/' + x)\ndf_22['filepath'] = df_22['filename'].apply(lambda x: str(train_22) + '/' + x)\ndf_21['filepath'] = df_21.apply(lambda row: build_path(row['primary_label'], row['filename']), axis=1)\n\ndf_23['filename'] = df_23['filename'].apply(lambda x: x.split('/')[-1] )\ndf_22['filename'] = df_22['filename'].apply(lambda x: x.split('/')[-1] )\n\nprint(f'Length of 2023 dataframe: {len(df_23)}')\ndf_23.head(3)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:51.556343Z","iopub.execute_input":"2023-03-27T01:36:51.556776Z","iopub.status.idle":"2023-03-27T01:36:52.591845Z","shell.execute_reply.started":"2023-03-27T01:36:51.556742Z","shell.execute_reply":"2023-03-27T01:36:52.590583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_dfs = pd.concat([df_23, df_22, df_21])\n\nprint(f'Length of the combined dataframe: {len(all_dfs)}')\nall_dfs.head(3)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:52.593856Z","iopub.execute_input":"2023-03-27T01:36:52.594343Z","iopub.status.idle":"2023-03-27T01:36:52.614568Z","shell.execute_reply.started":"2023-03-27T01:36:52.594300Z","shell.execute_reply":"2023-03-27T01:36:52.613759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now I can use the dictionary of unique files paths to filter out all duplicates","metadata":{}},{"cell_type":"code","source":"filter_list = [str(x) for x in all_sfiles.keys()]\nall_dfs = all_dfs[all_dfs['filepath'].isin(filter_list)]\n\nprint(f'Length of 2023 dataframe: {len(df_23)}')\nprint(f'Length of the combined dataframe: {len(all_dfs)}')\nprint(f'Expected length from number of unique files: {len(all_sfiles)}')","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:52.615715Z","iopub.execute_input":"2023-03-27T01:36:52.616546Z","iopub.status.idle":"2023-03-27T01:36:52.840946Z","shell.execute_reply.started":"2023-03-27T01:36:52.616491Z","shell.execute_reply":"2023-03-27T01:36:52.839701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_dfs.head()","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:52.842208Z","iopub.execute_input":"2023-03-27T01:36:52.842525Z","iopub.status.idle":"2023-03-27T01:36:52.855179Z","shell.execute_reply.started":"2023-03-27T01:36:52.842495Z","shell.execute_reply":"2023-03-27T01:36:52.853998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_23.to_csv(out_csv_23_pth, index=False)\nall_dfs.to_csv(out_csv_all_pth, index=False)","metadata":{"execution":{"iopub.status.busy":"2023-03-27T01:36:52.863022Z","iopub.execute_input":"2023-03-27T01:36:52.863370Z","iopub.status.idle":"2023-03-27T01:36:53.216786Z","shell.execute_reply.started":"2023-03-27T01:36:52.863338Z","shell.execute_reply":"2023-03-27T01:36:53.215294Z"},"trusted":true},"execution_count":null,"outputs":[]}]}