1385 lines (1384 with data), 32.2 kB
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# import libraries\n",
"import pandas as pd\n",
"import numpy as np\n",
"import umap\n",
"import plotly.express as px\n",
"from sklearn.preprocessing import StandardScaler"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Normalize the data\n",
"def is_data_normalized(data, tolerance=1e-3):\n",
" \"\"\"\n",
" Check if the data is normalized (mean ~ 0 and std ~ 1 for each column).\n",
"\n",
" Parameters:\n",
" data (np.ndarray): Data to check.\n",
" tolerance (float): Tolerance level for mean and std deviation.\n",
"\n",
" Returns:\n",
" bool: True if data is normalized, False otherwise.\n",
" \"\"\"\n",
" mean_check = np.allclose(np.mean(data, axis=0), 0, atol=tolerance)\n",
" std_check = np.allclose(np.std(data, axis=0), 1, atol=tolerance)\n",
" return mean_check and std_check\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Visualize single-cell data using UMAP\n",
"def visualize_umap(data, labels=None, n_neighbors=15, min_dist=0.1, n_components=2, random_state=42):\n",
" \"\"\"\n",
" Visualize single-cell gene expression data on a UMAP plot.\n",
"\n",
" Parameters:\n",
" data (pd.DataFrame or np.ndarray): Gene expression data. Rows are cells, columns are features/genes.\n",
" labels (pd.Series or np.ndarray, optional): Labels or annotations for the cells (e.g., cell type, tissue).\n",
" n_neighbors (int): Number of neighbors for UMAP.\n",
" min_dist (float): Minimum distance between points on the UMAP plot.\n",
" n_components (int): Number of dimensions for the UMAP embedding (default: 2 for 2D visualization).\n",
" random_state (int): Random state for reproducibility.\n",
"\n",
" Returns:\n",
" fig (plotly.graph_objects.Figure): Interactive UMAP plot.\n",
" \"\"\"\n",
" # Ensure data is in the right format\n",
" if isinstance(data, pd.DataFrame):\n",
" data_array = data.values\n",
" else:\n",
" data_array = data\n",
"\n",
" # Check if data is normalized\n",
" if not is_data_normalized(data_array):\n",
" print(\"Data is not normalized. Performing normalization...\")\n",
" data_scaled = StandardScaler().fit_transform(data_array)\n",
" else:\n",
" print(\"Data is already normalized. Skipping normalization...\")\n",
" data_scaled = data_array\n",
"\n",
" # Apply UMAP\n",
" umap_model = umap.UMAP(\n",
" n_neighbors=n_neighbors,\n",
" min_dist=min_dist,\n",
" n_components=n_components,\n",
" random_state=random_state\n",
" )\n",
" embedding = umap_model.fit_transform(data_scaled)\n",
"\n",
" # Create a DataFrame for the embedding\n",
" umap_df = pd.DataFrame(embedding, columns=[f\"UMAP_{i+1}\" for i in range(n_components)])\n",
"\n",
" # Add labels if provided\n",
" if labels is not None:\n",
" umap_df[\"Labels\"] = labels\n",
"\n",
" # Plot using Plotly\n",
" if n_components == 2:\n",
" fig = px.scatter(\n",
" umap_df, x=\"UMAP_1\", y=\"UMAP_2\",\n",
" color=\"Labels\" if labels is not None else None,\n",
" title=\"UMAP Visualization of Single-Cell Data\",\n",
" labels={\"Labels\": \"Annotations\"},\n",
" hover_data=umap_df.columns\n",
" )\n",
" elif n_components == 3:\n",
" fig = px.scatter_3d(\n",
" umap_df, x=\"UMAP_1\", y=\"UMAP_2\", z=\"UMAP_3\",\n",
" color=\"Labels\" if labels is not None else None,\n",
" title=\"UMAP Visualization of Single-Cell Data (3D)\",\n",
" labels={\"Labels\": \"Annotations\"},\n",
" hover_data=umap_df.columns\n",
" )\n",
" else:\n",
" raise ValueError(\"Only 2D and 3D visualizations are supported.\")\n",
"\n",
" # Customize plot appearance\n",
" fig.update_traces(marker=dict(size=5, opacity=0.8), selector=dict(mode=\"markers\"))\n",
" fig.update_layout(legend_title=\"Cell Annotations\", legend=dict(itemsizing=\"constant\"))\n",
"\n",
" return fig\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/jaydeepbhat/Documents/Hackathon/2024_AI_Agent/scripts/talk2cells/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Data is not normalized. Performing normalization...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/jaydeepbhat/Documents/Hackathon/2024_AI_Agent/scripts/talk2cells/lib/python3.11/site-packages/umap/umap_.py:1952: UserWarning: n_jobs value 1 overridden to 1 by setting random_state. Use no seed for parallelism.\n",
" warn(\n"
]
},
{
"data": {
"application/vnd.plotly.v1+json": {
"config": {
"plotlyServerURL": "https://plot.ly"
},
"data": [
{
"customdata": [
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
],
[
"Type C"
]
],
"hovertemplate": "Annotations=%{customdata[0]}<br>UMAP_1=%{x}<br>UMAP_2=%{y}<extra></extra>",
"legendgroup": "Type C",
"marker": {
"color": "#636efa",
"opacity": 0.8,
"size": 5,
"symbol": "circle"
},
"mode": "markers",
"name": "Type C",
"orientation": "v",
"showlegend": true,
"type": "scatter",
"x": {
"bdata": "g7aeP5DqSz+JfqE/kIybP2IslD95Y6I+oh3GP2eynz9Fdrg/nd9mv4VwsLzSzME+vevNP/3YVr6JfZ4/dqAlP5289j+Hqs8/hkLaP7V82j7rEJy/2MXRvqb0mz8PEwQ+r/Vgv9zrgj9X7fq+SxbkP2MQJz/0qgdAcCjYPio32j+5JwdA/x0WP2+Mszw=",
"dtype": "f4"
},
"xaxis": "x",
"y": {
"bdata": "LWJ6QGr1Y0ACDVtAWR+CQJ5JRkAMdkxAuQOSQJXCoUD0Ws1AemCkQJXFO0Dmb3RA4qc5QFM4okAqKkNAfvSAQDGWeUBlOsBAMVOnQJIYR0Bt7odAGx22QNYbEUCSVc9A6yyGQEG0C0Bp73lAa9zFQOOUnECBTyZANsClQB8qSEAznolANjGSQOMbXEA=",
"dtype": "f4"
},
"yaxis": "y"
},
{
"customdata": [
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
],
[
"Type A"
]
],
"hovertemplate": "Annotations=%{customdata[0]}<br>UMAP_1=%{x}<br>UMAP_2=%{y}<extra></extra>",
"legendgroup": "Type A",
"marker": {
"color": "#EF553B",
"opacity": 0.8,
"size": 5,
"symbol": "circle"
},
"mode": "markers",
"name": "Type A",
"orientation": "v",
"showlegend": true,
"type": "scatter",
"x": {
"bdata": "67SuvQCg3j/kNFY/urs9vkCnTj4YEpy/8SwCQLqQpLsttYk/87rmP0d2Pz5+XwA/gZE/P4GKtD1xyf0/TCGUP9XkAkBI14g/X2O4vinEN79FT34+aJHTPwGT/z9ahBI/iV8QvhE4uD8y27w/JUNJP3jNwD7HWCq/jT4Mv1me4D8yeVE/Ojp8PxqYBj/NxpG/",
"dtype": "f4"
},
"xaxis": "x",
"y": {
"bdata": "5rp1QP4wQ0C9wYBAuB7HQJ9PmUDhqpNAKgiVQDIOgEDUV49Ak8FpQJljykAeDGBAh8ogQGB7wUBPJp9A7N2qQERKlUDzniNAoXBOQPD8x0BfDI1AIssYQDFuqkDmIC5AVvqMQE1Oj0D5pyxAEMWaQFHgLkBDt1xAwzWPQDP3VUCivJVA4NWtQJrHt0CiiWpA",
"dtype": "f4"
},
"yaxis": "y"
},
{
"customdata": [
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
],
[
"Type B"
]
],
"hovertemplate": "Annotations=%{customdata[0]}<br>UMAP_1=%{x}<br>UMAP_2=%{y}<extra></extra>",
"legendgroup": "Type B",
"marker": {
"color": "#00cc96",
"opacity": 0.8,
"size": 5,
"symbol": "circle"
},
"mode": "markers",
"name": "Type B",
"orientation": "v",
"showlegend": true,
"type": "scatter",
"x": {
"bdata": "wdQtvySv2T+c4YO/gPHuPzEoh75mrglAj3VFP66WlT/AAYS/XSZkPwP+yj/5kIc/vDfWvnsnVT+Etuk+fYyRv6y0gzxOeBW/PBQlQEkwhb4Gkte+FjbcPZvooj7Uul2/MTAcQAIQGUCh/Ui/In4RQPcYG0A=",
"dtype": "f4"
},
"xaxis": "x",
"y": {
"bdata": "l1OjQOyAiECQdnVAUYm/QEiVnEC9SWJAu5u6QJXezUB3/pNAdLQ+QAu7rEClycJAV87OQEXNx0C9FdJAA2JzQEUrtEC777hADDagQMw3jEBIGmFAwxqNQKFP1kC3QrZAWUmOQAMbQ0D4UrxAoUM1QCLfpkA=",
"dtype": "f4"
},
"yaxis": "y"
}
],
"layout": {
"legend": {
"itemsizing": "constant",
"title": {
"text": "Cell Annotations"
},
"tracegroupgap": 0
},
"template": {
"data": {
"bar": [
{
"error_x": {
"color": "#2a3f5f"
},
"error_y": {
"color": "#2a3f5f"
},
"marker": {
"line": {
"color": "#E5ECF6",
"width": 0.5
},
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "bar"
}
],
"barpolar": [
{
"marker": {
"line": {
"color": "#E5ECF6",
"width": 0.5
},
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "barpolar"
}
],
"carpet": [
{
"aaxis": {
"endlinecolor": "#2a3f5f",
"gridcolor": "white",
"linecolor": "white",
"minorgridcolor": "white",
"startlinecolor": "#2a3f5f"
},
"baxis": {
"endlinecolor": "#2a3f5f",
"gridcolor": "white",
"linecolor": "white",
"minorgridcolor": "white",
"startlinecolor": "#2a3f5f"
},
"type": "carpet"
}
],
"choropleth": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "choropleth"
}
],
"contour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "contour"
}
],
"contourcarpet": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "contourcarpet"
}
],
"heatmap": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "heatmap"
}
],
"histogram": [
{
"marker": {
"pattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
}
},
"type": "histogram"
}
],
"histogram2d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "histogram2d"
}
],
"histogram2dcontour": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "histogram2dcontour"
}
],
"mesh3d": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"type": "mesh3d"
}
],
"parcoords": [
{
"line": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "parcoords"
}
],
"pie": [
{
"automargin": true,
"type": "pie"
}
],
"scatter": [
{
"fillpattern": {
"fillmode": "overlay",
"size": 10,
"solidity": 0.2
},
"type": "scatter"
}
],
"scatter3d": [
{
"line": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatter3d"
}
],
"scattercarpet": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattercarpet"
}
],
"scattergeo": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattergeo"
}
],
"scattergl": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattergl"
}
],
"scattermap": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattermap"
}
],
"scattermapbox": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scattermapbox"
}
],
"scatterpolar": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterpolar"
}
],
"scatterpolargl": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterpolargl"
}
],
"scatterternary": [
{
"marker": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"type": "scatterternary"
}
],
"surface": [
{
"colorbar": {
"outlinewidth": 0,
"ticks": ""
},
"colorscale": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"type": "surface"
}
],
"table": [
{
"cells": {
"fill": {
"color": "#EBF0F8"
},
"line": {
"color": "white"
}
},
"header": {
"fill": {
"color": "#C8D4E3"
},
"line": {
"color": "white"
}
},
"type": "table"
}
]
},
"layout": {
"annotationdefaults": {
"arrowcolor": "#2a3f5f",
"arrowhead": 0,
"arrowwidth": 1
},
"autotypenumbers": "strict",
"coloraxis": {
"colorbar": {
"outlinewidth": 0,
"ticks": ""
}
},
"colorscale": {
"diverging": [
[
0,
"#8e0152"
],
[
0.1,
"#c51b7d"
],
[
0.2,
"#de77ae"
],
[
0.3,
"#f1b6da"
],
[
0.4,
"#fde0ef"
],
[
0.5,
"#f7f7f7"
],
[
0.6,
"#e6f5d0"
],
[
0.7,
"#b8e186"
],
[
0.8,
"#7fbc41"
],
[
0.9,
"#4d9221"
],
[
1,
"#276419"
]
],
"sequential": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
],
"sequentialminus": [
[
0,
"#0d0887"
],
[
0.1111111111111111,
"#46039f"
],
[
0.2222222222222222,
"#7201a8"
],
[
0.3333333333333333,
"#9c179e"
],
[
0.4444444444444444,
"#bd3786"
],
[
0.5555555555555556,
"#d8576b"
],
[
0.6666666666666666,
"#ed7953"
],
[
0.7777777777777778,
"#fb9f3a"
],
[
0.8888888888888888,
"#fdca26"
],
[
1,
"#f0f921"
]
]
},
"colorway": [
"#636efa",
"#EF553B",
"#00cc96",
"#ab63fa",
"#FFA15A",
"#19d3f3",
"#FF6692",
"#B6E880",
"#FF97FF",
"#FECB52"
],
"font": {
"color": "#2a3f5f"
},
"geo": {
"bgcolor": "white",
"lakecolor": "white",
"landcolor": "#E5ECF6",
"showlakes": true,
"showland": true,
"subunitcolor": "white"
},
"hoverlabel": {
"align": "left"
},
"hovermode": "closest",
"mapbox": {
"style": "light"
},
"paper_bgcolor": "white",
"plot_bgcolor": "#E5ECF6",
"polar": {
"angularaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"bgcolor": "#E5ECF6",
"radialaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
}
},
"scene": {
"xaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
},
"yaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
},
"zaxis": {
"backgroundcolor": "#E5ECF6",
"gridcolor": "white",
"gridwidth": 2,
"linecolor": "white",
"showbackground": true,
"ticks": "",
"zerolinecolor": "white"
}
},
"shapedefaults": {
"line": {
"color": "#2a3f5f"
}
},
"ternary": {
"aaxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"baxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
},
"bgcolor": "#E5ECF6",
"caxis": {
"gridcolor": "white",
"linecolor": "white",
"ticks": ""
}
},
"title": {
"x": 0.05
},
"xaxis": {
"automargin": true,
"gridcolor": "white",
"linecolor": "white",
"ticks": "",
"title": {
"standoff": 15
},
"zerolinecolor": "white",
"zerolinewidth": 2
},
"yaxis": {
"automargin": true,
"gridcolor": "white",
"linecolor": "white",
"ticks": "",
"title": {
"standoff": 15
},
"zerolinecolor": "white",
"zerolinewidth": 2
}
}
},
"title": {
"text": "UMAP Visualization of Single-Cell Data"
},
"xaxis": {
"anchor": "y",
"domain": [
0,
1
],
"title": {
"text": "UMAP_1"
}
},
"yaxis": {
"anchor": "x",
"domain": [
0,
1
],
"title": {
"text": "UMAP_2"
}
}
}
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Example usage\n",
"if __name__ == \"__main__\":\n",
" # Simulated gene expression data (e.g., 100 cells with 50 genes each)\n",
" data = np.random.rand(100, 50)\n",
" labels = np.random.choice([\"Type A\", \"Type B\", \"Type C\"], size=100)\n",
"\n",
" # Create UMAP plot\n",
" fig = visualize_umap(data, labels=labels, n_components=2)\n",
" fig.show()\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "talk2cells",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.11"
}
},
"nbformat": 4,
"nbformat_minor": 2
}