{"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":"none","dataSources":[{"sourceId":53666,"databundleVersionId":6589269,"sourceType":"competition"}],"dockerImageVersionId":30587,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# CMI-SleepState-Detection\n## Child Mind Institute - Detect Sleep States\n### Detect sleep onset and wake from wrist-worn accelerometer data\n_______________________________________________________________________\n# [Kaggle Competition](https://www.kaggle.com/competitions/child-mind-institute-detect-sleep-states/overview)\n________________________________________________________________________\n# Author Details:\n### Name: Najeeb Haider Zaidi\n### Email: zaidi.nh@gmail.com\n### Profiles: [Github](https://github.com/snajeebz)  [LinkedIn](https://www.linkedin.com/in/najeebz) [Kaggle](https://www.kaggle.com/najeebz)\n### License: Private, Unlicensed, All the files in this repository under any branch are Prohibited to be used commercially or for personally, communally or privately unless permitted by author in writing.\n### Copyrights 2023-2024 (c) are reserved only by the author: Najeeb Haider Zaidi\n________________________________________________________________________\n# Attributions:\n## The Dataset has been provided by Child Mind Institute. in [Kaggle Competition](https://www.kaggle.com/competitions/child-mind-institute-detect-sleep-states/overview) which the author is participating in and authorized to use the dataset solely for the competition purposes.\n________________________________________________________________________\n\n### [Open in Kaggle](https://www.kaggle.com/najeebz/submission-preparation-notebook/)\n________________________________________________________________________","metadata":{}},{"cell_type":"markdown","source":"# Installing and Importing and Initializing Libraries.","metadata":{}},{"cell_type":"code","source":"import plotly.express as px\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\ntqdm.pandas()","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:13:24.541390Z","iopub.execute_input":"2023-12-07T20:13:24.541797Z","iopub.status.idle":"2023-12-07T20:13:24.549048Z","shell.execute_reply.started":"2023-12-07T20:13:24.541764Z","shell.execute_reply":"2023-12-07T20:13:24.546921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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)\n#from pandarallel import pandarallel\n\npd.set_option('display.max_row', 500)\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\nimport warnings\nwarnings.filterwarnings(\"ignore\")\npd.set_option('display.max_colwidth', None)\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n#pandarallel.initialize(progress_bar=True)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-12-07T20:13:24.551790Z","iopub.execute_input":"2023-12-07T20:13:24.552778Z","iopub.status.idle":"2023-12-07T20:13:24.566549Z","shell.execute_reply.started":"2023-12-07T20:13:24.552693Z","shell.execute_reply":"2023-12-07T20:13:24.565229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Windowing the training data\n### As the target is to detect an event, \n### So, extracting timesteps 30 min before and after the events. ","metadata":{}},{"cell_type":"code","source":"def window(df, win_size):\n    ind=df.index[df['event'].isna()==False]\n    c=0\n    df['window']=np.nan\n    for i in tqdm(ind):\n        a=i-win_size\n        b=i+win_size\n        df['window'].loc[a:i]=int(c)\n        c=c+1\n        df['window'].loc[i:b]=int(c)\n        c=c+1\n    df['window'].dropna(inplace=True)\n    return df[df['window'].isna()==False]\n\n#df_series=df_series[df_series['window'].isna()==False]","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:13:24.569695Z","iopub.execute_input":"2023-12-07T20:13:24.570196Z","iopub.status.idle":"2023-12-07T20:13:24.579529Z","shell.execute_reply.started":"2023-12-07T20:13:24.570165Z","shell.execute_reply":"2023-12-07T20:13:24.578160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Removing the steps where change in enmo and anglez is insignificant (device is supposed not to be worn)","metadata":{}},{"cell_type":"code","source":"def inactive_periods(df):\n    print(\"shape before application: \",df.shape)\n    df['diff_anglez']=df['anglez'].diff()\n    df=df[(df['enmo']!=0.0) | (df['diff_anglez']!=0.0)]\n    print(\"shape after application: \",df.shape)\n    df.drop('diff_anglez', inplace=True, axis=1)\n    print(\"shape after completion: \",df.shape)\n    print(\"removed \")\n    return df\n","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:13:24.581775Z","iopub.execute_input":"2023-12-07T20:13:24.582190Z","iopub.status.idle":"2023-12-07T20:13:24.601430Z","shell.execute_reply.started":"2023-12-07T20:13:24.582162Z","shell.execute_reply":"2023-12-07T20:13:24.599277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Clustering the Enmo and Anglez","metadata":{}},{"cell_type":"code","source":"def clustering(df):\n    from sklearn.cluster import KMeans\n    from sklearn.preprocessing import StandardScaler    \n    X=df[['anglez','enmo']]\n#Scalling the data\n    scaler=StandardScaler()\n    X_scaled=scaler.fit_transform(X)\n#perform clustering\n    model=KMeans(n_clusters=4,algorithm=\"elkan\" )\n    model.fit(X_scaled)\n    return model.labels_\n","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:13:24.603234Z","iopub.execute_input":"2023-12-07T20:13:24.603681Z","iopub.status.idle":"2023-12-07T20:13:24.616206Z","shell.execute_reply.started":"2023-12-07T20:13:24.603640Z","shell.execute_reply":"2023-12-07T20:13:24.613749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Adding Rolling Standard Deviations\n\n- As per observation enmo and anglez varies frequently and more than normal for few timesteps before and after the event.\n- In order to consider the variations into the modelling, using the method.","metadata":{}},{"cell_type":"code","source":" def rollingstd(series_df):\n# Creating columns with nans\n    series_df['sd_enmo_1']=np.nan    # 1 min rolling std: enmo\n    series_df['sd_anglez_1']=np.nan  # 1 min rolling std: anglez\n    series_df['m_enmo_2']=np.nan     # 2 min rolling mean: enmo\n    series_df['m_anglez_2']=np.nan   # 2 min rolling std: anglez \n    print('anglez rolling std 12')\n    series_df['sd_anglez_1'] = (series_df.groupby('series_id')['anglez']\n                      .rolling(12)\n                      .std()\n                      .reset_index(level=0, drop=True))\n    print('anglez rolling std 2')\n    series_df['sd_anglez_1'][series_df['sd_anglez_1'].isna()==True] = (series_df.groupby('series_id')['anglez']\n                      .rolling(2)\n                      .std()\n                      .reset_index(level=0, drop=True))\n    print('enmo rolling std 12')\n    series_df['sd_enmo_1'] = (series_df.groupby('series_id')['enmo']\n                      .rolling(12)\n                      .std()\n                      .reset_index(level=0, drop=True))\n    print('enmo rolling mean 24')\n    series_df['m_enmo_2'] = (series_df.groupby('series_id')['enmo']\n                      .rolling(24)\n                      .mean()\n                      .reset_index(level=0, drop=True))\n    print('anglez rolling mean 24')\n    series_df['m_anglez_2'] = (series_df.groupby('series_id')['anglez']\n                      .rolling(24)\n                      .mean()\n                      .reset_index(level=0, drop=True))\n    print('enmo rolling std 2')\n    print('Nans in sd_emno_1: ',series_df['sd_enmo_1'].isnull().sum())\n    series_df['sd_enmo_1'][series_df['sd_enmo_1'].isna()==True] = (series_df.groupby('series_id')['enmo']\n                      .rolling(2)\n                      .std()\n                      .reset_index(level=0, drop=True))\n    print('enmo rolling mean 2')\n    series_df['m_enmo_2'][series_df['m_enmo_2'].isna()==True] = (series_df.groupby('series_id')['enmo']\n                      .rolling(2)\n                      .mean()\n                      .reset_index(level=0, drop=True))\n    print('anglez rolling mean 2')\n    series_df['m_anglez_2'][series_df['m_anglez_2'].isna()==True] = (series_df.groupby('series_id')['anglez']\n                      .rolling(2)\n                      .mean()\n                      .reset_index(level=0, drop=True))\n#Series wise rolling std and mean\n# filling rest of nans\n    print('Nans in sd_emno_1: ',series_df['sd_enmo_1'].isnull().sum())\n    series_df['sd_enmo_1'].fillna(0.0, inplace=True)\n    series_df['sd_anglez_1'].fillna(0.0, inplace=True)\n    series_df['m_enmo_2'].fillna(0.0, inplace=True)\n    series_df['m_anglez_2'].fillna(0.0, inplace=True)\n    print('Nans after removal: ',series_df['sd_enmo_1'].isnull().sum())\n\n    return(series_df)","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:13:24.618377Z","iopub.execute_input":"2023-12-07T20:13:24.618993Z","iopub.status.idle":"2023-12-07T20:13:24.637965Z","shell.execute_reply.started":"2023-12-07T20:13:24.618946Z","shell.execute_reply":"2023-12-07T20:13:24.636206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Scaling the data","metadata":{}},{"cell_type":"code","source":"def scale(X):\n    from sklearn import preprocessing\n    scaler=preprocessing.StandardScaler().fit(X)\n    return (scaler.transform(X))","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:13:24.639055Z","iopub.execute_input":"2023-12-07T20:13:24.639367Z","iopub.status.idle":"2023-12-07T20:13:24.658304Z","shell.execute_reply.started":"2023-12-07T20:13:24.639342Z","shell.execute_reply":"2023-12-07T20:13:24.656728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Creating Training Data","metadata":{}},{"cell_type":"code","source":"# Importing the datasets\nprint('Importing Training Datasets')\ndf_series=pd.read_parquet(path=\"/kaggle/input/child-mind-institute-detect-sleep-states/train_series.parquet\", engine='auto')\ndf_events=pd.read_csv(\"/kaggle/input/child-mind-institute-detect-sleep-states/train_events.csv\")\nprint('Dataset Imported...')\nprint('______________________________________')\n\n# Merging the datasets\nprint('Merging the training datasets...')\nevents=df_events[['series_id', 'step','event']]\nseries_df=pd.merge(df_series,events,on=[\"step\",\"series_id\"],how='left')\ndf_series=[]\ndf_event=[]\nseries_df['sleep']=np.nan\nseries_df.loc[series_df[\"event\"]==\"onset\", \"sleep\"] = 1\nseries_df.loc[series_df[\"event\"]==\"wakeup\", \"sleep\"] = 0\nseries_df['sleep'].fillna(method='ffill', inplace=True)\nseries_df['sleep'].fillna(value=0, inplace=True)\nprint('Datasets Merged...')\nprint('______________________________________')\n\n# Removing the periods of inactivity\nprint('Removing the periods of Inactivity...')\nseries_df=inactive_periods(series_df)\nprint('______________________________________')\n\n# Forming Windows\nwin_size=720  #60mins\nprint('Creating Windows each size: ',win_size)\nseries_df=window(series_df,win_size)\nprint('Windows formed...')\nprint('______________________________________')\n\n# Adding the columns of Standard Deviation (1 min)\nprint('Adding columns to account for deviation in enmo and anglez 1 min rolling...')\nseries_df=rollingstd(series_df)\nseries_df['sd_anglez_1']=pd.to_numeric(series_df['sd_anglez_1'])\nseries_df['sd_enmo_1']=pd.to_numeric(series_df['sd_enmo_1'])\nseries_df['m_anglez_2']=pd.to_numeric(series_df['m_anglez_2'])\nseries_df['m_enmo_2']=pd.to_numeric(series_df['m_enmo_2'])\nprint('Std columns added...')\nprint('______________________________________')\n\n# Clustering the Data\nprint('Clustering the data based on enmo and anglez...')\nseries_df['cluster']=(clustering(series_df)+1)/4\nprint('Added clusters...')","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:13:24.660035Z","iopub.execute_input":"2023-12-07T20:13:24.660778Z","iopub.status.idle":"2023-12-07T20:18:39.586569Z","shell.execute_reply.started":"2023-12-07T20:13:24.660725Z","shell.execute_reply":"2023-12-07T20:18:39.584691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"series_df.dtypes","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:18:39.591594Z","iopub.execute_input":"2023-12-07T20:18:39.591962Z","iopub.status.idle":"2023-12-07T20:18:39.606014Z","shell.execute_reply.started":"2023-12-07T20:18:39.591932Z","shell.execute_reply":"2023-12-07T20:18:39.604569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"figure= px.imshow(series_df[['sd_anglez_1','sd_enmo_1','m_anglez_2','m_enmo_2','anglez','enmo','cluster','sleep']].corr(),text_auto=True, width=1200, height=1200)\nfigure.show()","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:18:39.607232Z","iopub.execute_input":"2023-12-07T20:18:39.607508Z","iopub.status.idle":"2023-12-07T20:18:43.586756Z","shell.execute_reply.started":"2023-12-07T20:18:39.607483Z","shell.execute_reply":"2023-12-07T20:18:43.585374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Creating Train Test Data from the Training Data","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nX=series_df[['sd_anglez_1','sd_enmo_1','anglez','m_anglez_2','m_enmo_2','enmo','cluster']]\ny=series_df[['sleep']]\nX_scaled=scale(X)\nX_train, X_test, y_train, y_test =train_test_split(X_scaled,y,test_size=0.2, random_state=42)\ndel X\ndel y","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:19:36.564268Z","iopub.execute_input":"2023-12-07T20:19:36.564834Z","iopub.status.idle":"2023-12-07T20:19:40.100052Z","shell.execute_reply.started":"2023-12-07T20:19:36.564770Z","shell.execute_reply":"2023-12-07T20:19:40.098376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_test[['sleep']].value_counts()","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:19:48.891652Z","iopub.execute_input":"2023-12-07T20:19:48.892464Z","iopub.status.idle":"2023-12-07T20:19:48.954362Z","shell.execute_reply.started":"2023-12-07T20:19:48.892418Z","shell.execute_reply":"2023-12-07T20:19:48.952766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Function to evaluate the training (scikit-Learn)","metadata":{}},{"cell_type":"code","source":"def evaluate(y_test,ypred):\n    from sklearn.metrics import precision_score\n    from sklearn.metrics import recall_score\n    from sklearn.metrics import f1_score\n    from sklearn.metrics import accuracy_score\n    from sklearn.metrics import confusion_matrix\n    print(\"Accuracy: \",accuracy_score(y_test,y_pred)) \n    print(\"Precision Score : \", precision_score(y_test,y_pred)) #precision measures the proportion of true positive predictions among all positive instances. how many of survived predicted actually survived, doesn't verifies 0's 70 survived as preicted whereas actually 92 survived so 70/92 will be the precision.  if we predicted 70 survived, so presion will tell how many of those 70 predicted survived matches the actual row by row data. It checkes all positives and verifies if the answer is true for each row?\n    print(\"Recall Score: \", recall_score(y_test,y_pred, average='macro')) #Recall measures the proportion of true positive predictions among all actual positive instalnces. If we predicted 100 survived correctly whereas actually 100 survived out of which 67 predicted correctly so recall will be 0.67\n    print(\"F1 Score: \",f1_score(y_test,y_pred)) #mean of recall and precision\n    cm = confusion_matrix(y_test, y_pred)\n    figure= px.imshow(cm,text_auto=True, width=1200, height=1200)\n    figure.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:19:57.869345Z","iopub.execute_input":"2023-12-07T20:19:57.869780Z","iopub.status.idle":"2023-12-07T20:19:57.879836Z","shell.execute_reply.started":"2023-12-07T20:19:57.869742Z","shell.execute_reply":"2023-12-07T20:19:57.878289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training MLP Classifier","metadata":{}},{"cell_type":"code","source":"from sklearn.neural_network import MLPClassifier\nclf = MLPClassifier(solver='adam', \n              max_iter =100, \n              alpha=10, \n              hidden_layer_sizes=5, \n              random_state=5,\n              activation='relu',\n              batch_size=360, \n              learning_rate='adaptive', \n              verbose=1,\n              early_stopping=1, \n              n_iter_no_change=10)\n\nprint ('Training the model')\nclf.fit(X_train,y_train)\nprint(clf.score(X_train,y_train))\nprint ('Saving the model')\nfrom joblib import dump, load\ndump(clf, 'mlp_model.joblib')\ny_pred=clf.predict(X_test)\nevaluate(y_test,y_pred)","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:20:04.764682Z","iopub.execute_input":"2023-12-07T20:20:04.765065Z","iopub.status.idle":"2023-12-07T20:22:13.066511Z","shell.execute_reply.started":"2023-12-07T20:20:04.765038Z","shell.execute_reply":"2023-12-07T20:22:13.064480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training Random Forest Classifier","metadata":{}},{"cell_type":"code","source":"from sklearn.ensemble import RandomForestClassifier\nrf =RandomForestClassifier(n_jobs=-1,verbose=1) \nprint ('Training the model')\nrf.fit(X_train,y_train)\nprint ('Saving the model')\nfrom joblib import dump, load\ndump(rf, 'rf_model.joblib')\ny_pred=rf.predict(X_test)\nevaluate(y_test,y_pred)","metadata":{"execution":{"iopub.status.busy":"2023-12-07T20:24:32.880896Z","iopub.execute_input":"2023-12-07T20:24:32.881408Z","iopub.status.idle":"2023-12-07T21:05:38.885080Z","shell.execute_reply.started":"2023-12-07T20:24:32.881369Z","shell.execute_reply":"2023-12-07T21:05:38.883150Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preparing Testing Dataset","metadata":{}},{"cell_type":"code","source":"# Importing the datasets\nprint('Importing Testing Datasets')\ntest_series=pd.read_parquet(path=\"/kaggle/input/child-mind-institute-detect-sleep-states/test_series.parquet\", engine='auto')\nprint('Dataset Imported...')\nprint('______________________________________')\n\n# Removing the periods of inactivity\nprint('Removing the periods of Inactivity...')\ntest_series=inactive_periods(test_series)\nprint('______________________________________')\n\n# Adding Features\nprint('Adding Features...')\ntest_series=rollingstd(test_series)\ntest_series['sd_anglez_1']=pd.to_numeric(test_series['sd_anglez_1'])\ntest_series['sd_enmo_1']=pd.to_numeric(test_series['sd_enmo_1'])\ntest_series['m_anglez_2']=pd.to_numeric(test_series['m_anglez_2'])\ntest_series['m_enmo_2']=pd.to_numeric(test_series['m_enmo_2'])\nprint('Features added...')\nprint('______________________________________')\n\n# Clustering the Data\nprint('Clustering the data based on enmo and anglez...')\ntest_series['cluster']=(clustering(test_series)+1)/4\nprint('Added clusters...')\n\nX_test=test_series[['sd_anglez_1','sd_enmo_1','anglez','m_anglez_2','m_enmo_2','enmo','cluster']]\n\ny_pred=rf.predict(scale(X_test))\nX_test=[]","metadata":{"execution":{"iopub.status.busy":"2023-12-07T21:10:10.322651Z","iopub.execute_input":"2023-12-07T21:10:10.323244Z","iopub.status.idle":"2023-12-07T21:10:10.557946Z","shell.execute_reply.started":"2023-12-07T21:10:10.323197Z","shell.execute_reply":"2023-12-07T21:10:10.556993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preparing Submission File","metadata":{}},{"cell_type":"code","source":"result_df=test_series[['series_id', 'step','timestamp']]\nresult_df['sleep']=y_pred\nresult_df['timestamp']=result_df[['timestamp']].progress_apply(lambda x: pd.to_datetime(x,utc=True))\ndf=result_df.copy()\ndf.index=df['timestamp']\nmean = df.groupby([df['series_id'], df.index.floor('5min')])['sleep'].mean()  # Calculating the mean of predictions over an interval of 5 mins (Due to the nature of Testing Data Series). \nmean=mean.reset_index()\nmean['timestamp']=mean['timestamp']- pd.to_timedelta('5m') # Since the event is recorded at the end of the interval so subtracting 5 mins (Due to the nature of Testing Data Series) so it records the event at the start of the interval\nsummary=pd.merge(result_df,mean,on=[\"timestamp\",\"series_id\"],how='left')  # merging the means into the original data based on timestamps and series ID.\nsummary=summary[summary['sleep_y'].isna()==False]  # removing the Nan's of prediction mean. That'll ensure that we have a row every 5 mins (Due to the nature of Testing Data Series).\n# Creating Event Column\nsummary['event']=np.nan\nsummary.loc[summary[\"sleep_y\"]==1, \"event\"] = 'onset'  # the mean prediction will be 1 if predicted onset for 30 mins consecutive\nsummary.loc[summary[\"sleep_y\"]==0, \"event\"] = 'wakeup' # the mean prediction will be 0 if predicted wakeup for 30 mins consecutive. Any duration in between will be considered disturbance as will be less tan 30 mins.\nsummary=summary[summary['event'].isna()==False] # Removing the rows with no event recorded. \nsubmission=summary[['series_id','step','event','sleep_y']]  # Creating Submission\nsubmission = submission.rename(columns={'sleep_y': 'score'})  # Renaming a column\n\nsubmission.to_csv('submission.csv')  # Saving the csv file","metadata":{"execution":{"iopub.status.busy":"2023-12-07T21:13:45.440564Z","iopub.execute_input":"2023-12-07T21:13:45.442057Z","iopub.status.idle":"2023-12-07T21:13:45.486503Z","shell.execute_reply.started":"2023-12-07T21:13:45.441981Z","shell.execute_reply":"2023-12-07T21:13:45.484642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2023-12-07T21:13:48.096789Z","iopub.execute_input":"2023-12-07T21:13:48.097270Z","iopub.status.idle":"2023-12-07T21:13:48.113656Z","shell.execute_reply.started":"2023-12-07T21:13:48.097232Z","shell.execute_reply":"2023-12-07T21:13:48.111339Z"},"trusted":true},"execution_count":null,"outputs":[]}]}