{"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":"# What is about ? \n\nWe convert multiome targets (i.e. single cell RNA sequencing data) to \"anndata\" format - a kind of \"dataframe on steroids\" which is standard in single cell RNA sequencing area. \n\n\n**AnnData - dataframe on steroids.** In a nutshell \"anndata\" - is similar to pandas dataframe , but both \"columns\" and \"index\" - are dataframes themselves - so allow to store more meta-information; while \".values\" can be both \"sparse\" and standard dense numpy matrices.\nOne is advised to look at \"scanpy tutorials\" for further information: https://scanpy.readthedocs.io/en/stable/tutorials.html .\nSome examples can be found in https://www.kaggle.com/datasets/alexandervc/scanpy-python-package-for-scrnaseq-analysis .\n(Also look https://www.kaggle.com/alexandervc/datasets and code therein for more examples). \n\n\n**WARNING!** Early versions of that script 1-3 contained incorrect assigments of gene symbols. Due to unexpected behaviour of \"mygene\" - quering for list of genes it sometimes returns duplicates of some queries - that was unexpected (did not happen before) and caused incorrecte assignments.  From version 4 - that problem is corrected. We use detailed genes information   prepared in the separet script: https://www.kaggle.com/code/alexandervc/mmscel-genes-eda . \n\nThe produced \"anndata\" is stored in dataset: https://www.kaggle.com/datasets/alexandervc/scrnaseq-competition-open-problems-adata-fmt\n\n\nSo created \"anndata\":\n\n    1) Data - in sparse matrix format. (Sparse matrix was taken from SBUNZINI https://www.kaggle.com/datasets/sbunzini/open-problems-msci-multiome-sparse-matrices ) \n\n    2) Keep meta information - e.g. cell_types, donors, days at the same anndata - i.e. information from the file \"FP_CELL_METADATA\" is joined. Also we add genes SYMBOLS, (not only Ensemble Ids) - using package mygene - and lots of other information on genes prepared in the script mentioned above. \n\n    3) It can be stored as zipped file - so less size and thus faster loading\n\n    4) Almost all standard  software works with \"anndata\"\n\nTo load it: \n\n    !pip install scanpy\n    import scanpy as sc\n    adata = sc.read( filename )\n    adata.X - the data (sparse matrix by SBUNZINI) - analogue of df.values\n    adata.obs - metadata on cells (pandas dataframe) - analogue of df.index\n    adata.var - metdata on genes  (pandas dataframe) - analogue of df.columns \n    \n    One can work with it NOT loading to RAM, but backing on disk:\n    adata = sc.read(fn,  backed='r' )\n    ","metadata":{}},{"cell_type":"markdown","source":"# Install/Import","metadata":{}},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\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\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-09-19T06:58:02.217334Z","iopub.execute_input":"2022-09-19T06:58:02.217827Z","iopub.status.idle":"2022-09-19T06:58:02.281506Z","shell.execute_reply.started":"2022-09-19T06:58:02.217729Z","shell.execute_reply":"2022-09-19T06:58:02.280434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install scanpy\nimport scanpy as sc\nimport anndata\n\nimport time\nt0start = time.time()\n\nimport pandas as pd\nimport numpy as np\nimport os\nimport sys\n\nimport matplotlib.pyplot as plt\n#plt.style.use('dark_background')\nimport seaborn as sns\n\n#If you see a urllib warning running this cell, go to \"Settings\" on the right hand side, \n#and turn on internet. Note, you need to be phone verified.\n!pip install --quiet tables\n\n\nimport h5py\n!pip install hdf5plugin~=2.0 # https://forum.hdfgroup.org/t/cant-open-directory-usr-local-hdf5-lib-plugin/9738/4\nimport hdf5plugin","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:58:02.283605Z","iopub.execute_input":"2022-09-19T06:58:02.284055Z","iopub.status.idle":"2022-09-19T06:58:47.233803Z","shell.execute_reply.started":"2022-09-19T06:58:02.284010Z","shell.execute_reply":"2022-09-19T06:58:47.232443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATA_DIR = \"/kaggle/input/open-problems-multimodal/\"\nFP_CELL_METADATA = os.path.join(DATA_DIR,\"metadata.csv\")\n\nFP_CITE_TRAIN_INPUTS = os.path.join(DATA_DIR,\"train_cite_inputs.h5\")\nFP_CITE_TRAIN_TARGETS = os.path.join(DATA_DIR,\"train_cite_targets.h5\")\nFP_CITE_TEST_INPUTS = os.path.join(DATA_DIR,\"test_cite_inputs.h5\")\n\nFP_MULTIOME_TRAIN_INPUTS = os.path.join(DATA_DIR,\"train_multi_inputs.h5\")\nFP_MULTIOME_TRAIN_TARGETS = os.path.join(DATA_DIR,\"train_multi_targets.h5\")\nFP_MULTIOME_TEST_INPUTS = os.path.join(DATA_DIR,\"test_multi_inputs.h5\")\n\nFP_SUBMISSION = os.path.join(DATA_DIR,\"sample_submission.csv\")\nFP_EVALUATION_IDS = os.path.join(DATA_DIR,\"evaluation_ids.csv\")\n\ndf_cell = pd.read_csv(FP_CELL_METADATA)\ndf_cell","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:58:47.236308Z","iopub.execute_input":"2022-09-19T06:58:47.236837Z","iopub.status.idle":"2022-09-19T06:58:47.677406Z","shell.execute_reply.started":"2022-09-19T06:58:47.236785Z","shell.execute_reply":"2022-09-19T06:58:47.676159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load multiome targets in sparse format","metadata":{}},{"cell_type":"code","source":"%%time\nimport scipy.sparse\nfn = '/kaggle/input/open-problems-msci-multiome-sparse-matrices/train_multi_targets_sparse.npz'\n#fn = '/kaggle/input/open-problems-msci-multiome-sparse-matrices/train_multiome_input_sparse.npz'\nX = scipy.sparse.load_npz(fn)# \"../input/multimodal-single-cell-as-sparse-matrix/train_multi_inputs_values.sparse.npz\")\nprint(X.shape)\ndisplay(X)","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:58:47.679749Z","iopub.execute_input":"2022-09-19T06:58:47.680116Z","iopub.status.idle":"2022-09-19T06:59:16.476975Z","shell.execute_reply.started":"2022-09-19T06:58:47.680084Z","shell.execute_reply":"2022-09-19T06:59:16.475903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"type(X)\n","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:16.478799Z","iopub.execute_input":"2022-09-19T06:59:16.479515Z","iopub.status.idle":"2022-09-19T06:59:16.487541Z","shell.execute_reply.started":"2022-09-19T06:59:16.479469Z","shell.execute_reply":"2022-09-19T06:59:16.486527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('4.7G RAM consumed')","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:16.488710Z","iopub.execute_input":"2022-09-19T06:59:16.489009Z","iopub.status.idle":"2022-09-19T06:59:16.499258Z","shell.execute_reply.started":"2022-09-19T06:59:16.488982Z","shell.execute_reply":"2022-09-19T06:59:16.498120Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#adata = sc.AnnData(X = X)# , dtype = np.float16)","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:16.500549Z","iopub.execute_input":"2022-09-19T06:59:16.500957Z","iopub.status.idle":"2022-09-19T06:59:16.509717Z","shell.execute_reply.started":"2022-09-19T06:59:16.500929Z","shell.execute_reply":"2022-09-19T06:59:16.508345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load cell_ids from  train_multi_targets.h5","metadata":{}},{"cell_type":"code","source":"print()\nprint('Look on TARGETs: ')\nfilename = '/kaggle/input/open-problems-multimodal/train_multi_targets.h5'\nf = h5py.File(filename,'r')#, mode)\nprint('fragment of a DNA Ids:')\nprint( f['train_multi_targets']['axis0'][:5] )\nprint('Cell Ids (seems to me):')\nprint( f['train_multi_targets']['axis1'].shape)\nprint('First:')\nprint( f['train_multi_targets']['axis1'][:15] )\nprint('Last:')\nprint( f['train_multi_targets']['axis1'][-15:] )","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:16.512669Z","iopub.execute_input":"2022-09-19T06:59:16.513473Z","iopub.status.idle":"2022-09-19T06:59:16.546387Z","shell.execute_reply.started":"2022-09-19T06:59:16.513425Z","shell.execute_reply":"2022-09-19T06:59:16.545163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nbarcodes = [t.decode() for t in f['train_multi_targets']['axis1'] ]\nprint(barcodes[:15])\nprint(barcodes[-15:])","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:16.548170Z","iopub.execute_input":"2022-09-19T06:59:16.548854Z","iopub.status.idle":"2022-09-19T06:59:26.169851Z","shell.execute_reply.started":"2022-09-19T06:59:16.548810Z","shell.execute_reply":"2022-09-19T06:59:26.168638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Sanity check - cell_ids coincide with those loaded by organizers proposed way (read_hdf)","metadata":{}},{"cell_type":"code","source":"%%time\nSTART = 0\nSTOP = 1_000\ndf_multi_train_y = pd.read_hdf(FP_MULTIOME_TRAIN_TARGETS, start=START, stop=STOP)\ndisplay(df_multi_train_y.head())","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:26.173863Z","iopub.execute_input":"2022-09-19T06:59:26.174242Z","iopub.status.idle":"2022-09-19T06:59:27.197710Z","shell.execute_reply.started":"2022-09-19T06:59:26.174212Z","shell.execute_reply":"2022-09-19T06:59:27.196452Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(barcodes)","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:27.199479Z","iopub.execute_input":"2022-09-19T06:59:27.200312Z","iopub.status.idle":"2022-09-19T06:59:27.208097Z","shell.execute_reply.started":"2022-09-19T06:59:27.200267Z","shell.execute_reply":"2022-09-19T06:59:27.206861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"START = 105942-15\nSTOP = 105942\ndf_multi_train_y = pd.read_hdf(FP_MULTIOME_TRAIN_TARGETS, start=START, stop=STOP)\ndisplay(df_multi_train_y.head())","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:27.209750Z","iopub.execute_input":"2022-09-19T06:59:27.210099Z","iopub.status.idle":"2022-09-19T06:59:27.359793Z","shell.execute_reply.started":"2022-09-19T06:59:27.210068Z","shell.execute_reply":"2022-09-19T06:59:27.358435Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_multi_train_y.index[-15:]","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:27.361862Z","iopub.execute_input":"2022-09-19T06:59:27.362305Z","iopub.status.idle":"2022-09-19T06:59:27.370635Z","shell.execute_reply.started":"2022-09-19T06:59:27.362262Z","shell.execute_reply":"2022-09-19T06:59:27.369440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(barcodes[-15:])","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:27.372204Z","iopub.execute_input":"2022-09-19T06:59:27.372656Z","iopub.status.idle":"2022-09-19T06:59:27.382009Z","shell.execute_reply.started":"2022-09-19T06:59:27.372623Z","shell.execute_reply":"2022-09-19T06:59:27.380741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# A bit strange thing - in METADATA FILE the targets of multiome are not placed fully consequent - two gaps. But it is not a problem","metadata":{}},{"cell_type":"code","source":"df_cell.iloc[152603:152618,:]['cell_id'].values","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:27.383653Z","iopub.execute_input":"2022-09-19T06:59:27.384029Z","iopub.status.idle":"2022-09-19T06:59:27.398002Z","shell.execute_reply.started":"2022-09-19T06:59:27.383998Z","shell.execute_reply":"2022-09-19T06:59:27.397066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('In df_cell the indexes of train multiome are not quite consequent')\nm = df_cell['cell_id'].isin(barcodes)\nprint(df_cell.shape)\nplt.plot(df_cell[m].index)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:27.399592Z","iopub.execute_input":"2022-09-19T06:59:27.400049Z","iopub.status.idle":"2022-09-19T06:59:27.915611Z","shell.execute_reply.started":"2022-09-19T06:59:27.400002Z","shell.execute_reply":"2022-09-19T06:59:27.914802Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"m = (df_cell['cell_id'].isin(barcodes))\nm.sum(), len(barcodes)","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:27.916668Z","iopub.execute_input":"2022-09-19T06:59:27.917832Z","iopub.status.idle":"2022-09-19T06:59:28.005500Z","shell.execute_reply.started":"2022-09-19T06:59:27.917784Z","shell.execute_reply":"2022-09-19T06:59:28.004165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create metadata for cells ","metadata":{}},{"cell_type":"code","source":"obs = pd.DataFrame(index = barcodes)\nd = df_cell.reset_index().set_index('cell_id') \nd.columns = ['Index in df_cell'] + list(d.columns[1:])\nobs = obs.join(d, how = 'left', )\nobs","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:28.006834Z","iopub.execute_input":"2022-09-19T06:59:28.007797Z","iopub.status.idle":"2022-09-19T06:59:28.196764Z","shell.execute_reply.started":"2022-09-19T06:59:28.007753Z","shell.execute_reply":"2022-09-19T06:59:28.195571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create AnnData","metadata":{}},{"cell_type":"code","source":"# We have not seen storage reduction at least on disk for float16 - anyway one can make conversion after loading \n# X = scipy.sparse.csr_matrix(X, dtype = np.float16)\nadata = sc.AnnData(X = X)# , dtype = np.float16)","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:28.198424Z","iopub.execute_input":"2022-09-19T06:59:28.198795Z","iopub.status.idle":"2022-09-19T06:59:28.341480Z","shell.execute_reply.started":"2022-09-19T06:59:28.198765Z","shell.execute_reply":"2022-09-19T06:59:28.340102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"adata.obs = obs","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:28.343347Z","iopub.execute_input":"2022-09-19T06:59:28.343829Z","iopub.status.idle":"2022-09-19T06:59:28.363315Z","shell.execute_reply.started":"2022-09-19T06:59:28.343784Z","shell.execute_reply":"2022-09-19T06:59:28.361942Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create metadata for genes - add symbol names","metadata":{}},{"cell_type":"code","source":"list_ensembl_ids = list(df_multi_train_y.columns)\nprint(list_ensembl_ids[:15])","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:28.364951Z","iopub.execute_input":"2022-09-19T06:59:28.365593Z","iopub.status.idle":"2022-09-19T06:59:28.373476Z","shell.execute_reply.started":"2022-09-19T06:59:28.365557Z","shell.execute_reply":"2022-09-19T06:59:28.372269Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fn2= '/kaggle/input/genes-information/genes_information_mmscel_challenge_multiome_subtask_tf_info.csv'\nvar = pd.read_csv(fn2, index_col = 0)\nvar","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:28.375228Z","iopub.execute_input":"2022-09-19T06:59:28.375670Z","iopub.status.idle":"2022-09-19T06:59:28.872564Z","shell.execute_reply.started":"2022-09-19T06:59:28.375638Z","shell.execute_reply":"2022-09-19T06:59:28.871339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"list_ensembl_ids ==  list(var['ensembl_id'])\n","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:28.874099Z","iopub.execute_input":"2022-09-19T06:59:28.874499Z","iopub.status.idle":"2022-09-19T06:59:28.884487Z","shell.execute_reply.started":"2022-09-19T06:59:28.874463Z","shell.execute_reply":"2022-09-19T06:59:28.883425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# It works not quite correctly - \n# unexpected use of \"mygene\" - quering for list of genes it sometimes returns duplicates of some queries - that was unexpected (did not happen before) and caused incorrecte assignments. \n\n# Script : https://www.kaggle.com/code/alexandervc/mmscel-genes-eda\n# correctly works with duplicates and add lots lots of more information.\n\n# !pip install mygene\n# import mygene\n# import time\n\n# t0 = time.time()\n# mg = mygene.MyGeneInfo()\n# g = mg.getgenes(list_ensembl_ids)# [:1000])\n# print('%.f seconds passed'%(time.time()-t0))\n\n# t0 = time.time()\n# var = pd.DataFrame()\n# for i in range(len(list_ensembl_ids)):\n#     var.loc[i , 'Ensembl'] = list_ensembl_ids[i]\n#     if 'symbol' in g[i].keys():\n#         var.loc[i , 'Symbol'] = g[i]['symbol']\n#     else:\n#         var.loc[i , 'Symbol'] = list_ensembl_ids[i]\n\n# print('%.f seconds passed'%(time.time()-t0))        \n# var = var.set_index('Symbol')\n# var","metadata":{"execution":{"iopub.status.busy":"2022-09-19T07:03:52.593077Z","iopub.execute_input":"2022-09-19T07:03:52.593805Z","iopub.status.idle":"2022-09-19T07:03:52.602140Z","shell.execute_reply.started":"2022-09-19T07:03:52.593728Z","shell.execute_reply":"2022-09-19T07:03:52.600667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"adata.var = var\nadata","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:28.899233Z","iopub.execute_input":"2022-09-19T06:59:28.900455Z","iopub.status.idle":"2022-09-19T06:59:28.913741Z","shell.execute_reply.started":"2022-09-19T06:59:28.900406Z","shell.execute_reply":"2022-09-19T06:59:28.912321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"adata.var.index","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:28.915063Z","iopub.execute_input":"2022-09-19T06:59:28.915417Z","iopub.status.idle":"2022-09-19T06:59:28.923934Z","shell.execute_reply.started":"2022-09-19T06:59:28.915388Z","shell.execute_reply":"2022-09-19T06:59:28.923101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Save to disk","metadata":{}},{"cell_type":"code","source":"import time\nt0 = time.time()\nfn = 'train_multi_targets_sparse.h5ad'\nadata.write_h5ad(fn,compression='gzip')\nprint('%.1f seconds passed'%(time.time()-t0))\nadata","metadata":{"execution":{"iopub.status.busy":"2022-09-19T06:59:28.925288Z","iopub.execute_input":"2022-09-19T06:59:28.925653Z","iopub.status.idle":"2022-09-19T07:01:18.305703Z","shell.execute_reply.started":"2022-09-19T06:59:28.925622Z","shell.execute_reply":"2022-09-19T07:01:18.304060Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test Load of saved data","metadata":{}},{"cell_type":"code","source":"atest = sc.read( 'train_multi_targets_sparse.h5ad' )\natest ","metadata":{"execution":{"iopub.status.busy":"2022-09-19T07:04:45.348618Z","iopub.execute_input":"2022-09-19T07:04:45.349148Z","iopub.status.idle":"2022-09-19T07:05:05.089092Z","shell.execute_reply.started":"2022-09-19T07:04:45.349106Z","shell.execute_reply":"2022-09-19T07:05:05.087924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('9.1G RAM  consumed')","metadata":{"execution":{"iopub.status.busy":"2022-09-19T07:06:49.937951Z","iopub.execute_input":"2022-09-19T07:06:49.938487Z","iopub.status.idle":"2022-09-19T07:06:49.944256Z","shell.execute_reply.started":"2022-09-19T07:06:49.938452Z","shell.execute_reply":"2022-09-19T07:06:49.943405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('%.1f seconds passed total '%(time.time()-t0start) )","metadata":{"execution":{"iopub.status.busy":"2022-09-19T07:05:39.449539Z","iopub.execute_input":"2022-09-19T07:05:39.450020Z","iopub.status.idle":"2022-09-19T07:05:39.456251Z","shell.execute_reply.started":"2022-09-19T07:05:39.449981Z","shell.execute_reply":"2022-09-19T07:05:39.455316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}