diff --git a/Docker.md b/Docker.md new file mode 100644 index 0000000..df12223 --- /dev/null +++ b/Docker.md @@ -0,0 +1,83 @@ +## Docker镜像使用说明 + +STABOX所需的依赖环境已提供为Docker镜像,方便用户快速部署。 + +## 下载 Docker 镜像 + +请从以下链接下载STABOX的Docker镜像压缩文件(XZ格式): + +[下载链接](https://drive.google.com/drive/folders/1E1u3BdQH5oguPvfY2y2kxDWnYbStZSoJ?usp=sharing) + +下载完成后,使用以下命令解压文件: + +```bash +xz -d -T0 zhanglab_stabox.tar.xz +``` + +其中,`-T0`选项表示自动选择多个CPU进行解压,以加快解压速度。 + +## 加载 Docker 镜像 + +确保你已经安装并配置了Docker环境。然后使用以下命令加载镜像: + +```bash +docker load -i zhanglab_stabox.tar +``` + +可以通过以下命令查看已加载的镜像: + +```bash +docker images +``` + +应该可以看到 `zhanglab_stabox` 镜像。 + +## 运行 Docker 容器 + +运行容器时,可以通过以下命令启动容器: + +```bash +docker run --gpus all -it -v /mnt/disk1/LZJ/project/STABox:/home -d zhanglab_stabox +``` + +- `--gpus all`:表示允许容器访问宿主机的所有GPU。 +- `-v /mnt/disk1/LZJ/project/STABox:/home`:此参数将本地的STABox代码目录映射到Docker容器的`/home`目录,便于在容器中运行代码。 + +## GPU 支持问题 + +如果你遇到以下错误: + +```bash +docker: Error response from daemon: could not select device driver "" with capabilities: [[gpu]]. +``` + +说明你的Docker环境目前不支持GPU。要启用GPU支持,请按照以下步骤安装 `nvidia-docker2`: + +1. 安装 `nvidia-container-toolkit`: + +```bash +curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list +``` + +2. 更新 apt 包列表并安装 `nvidia-container-toolkit`: + +```bash +sudo apt-get update +sudo apt-get install -y nvidia-container-toolkit +``` + +3. 配置 Docker 使用 NVIDIA GPU: + +```bash +sudo nvidia-ctk runtime configure --runtime=docker +``` + +4. 重启 Docker 服务: + +```bash +sudo systemctl restart docker +``` + +## 运行 STABOX + +完成以上设置后,你就可以在Docker容器中运行STABOX进行训练、测试、预测等操作。 diff --git a/README.md b/README.md index 2b8c918..45676fd 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ conda create -n env_STABox python=3.8 #activate your environment conda activate env_STABox +详细步骤见同级的README_DETAIL.md文件 + ``` @@ -104,3 +106,6 @@ Q: How to install **PyG** from whl files? A: Please download the whl files from https://pytorch-geometric.com/whl/index.html. Note that the version of python, torch, PyG, and cuda should match. +Q: Would it be more convenient if the dependencies for STABOX could be packaged into Docker images? + +A: Yes, using Docker containers can simplify environment configuration and dependency management. Here are the basic steps to create a Docker image:[here](/Docker.md) diff --git a/README_DETAIL.md b/README_DETAIL.md new file mode 100644 index 0000000..b9021bd --- /dev/null +++ b/README_DETAIL.md @@ -0,0 +1,109 @@ +``` +# 从零开始搭建STABox环境 + +1. 创建并激活环境: + ```bash + conda create -n stomics python=3.10 + conda activate stomics + ``` + +2. 安装必要的包: + ```bash + pip install 'scanpy[leiden]' + pip install requests + ``` + +3. 查看显卡驱动版本: + ```bash + nvidia-smi + ``` + + 输出示例: + ``` + +---------------------------------------------------------------------------------------+ + | NVIDIA-SMI 535.183.01 Driver Version: 535.183.01 CUDA Version: 12.2 | + |-----------------------------------------+----------------------+----------------------+ + ``` + +4. 安装 PyTorch: + ```bash + pip3 install torch torchvision torchaudio + ``` + > 注意:此时 torch 版本是 2.4.1,后面安装 dgl 库会删除 torch 2.4.1,转而安装 torch 2.4.0,影响不大。 + +5. 查看已安装包: + ```bash + pip list + ``` + +6. 安装其他依赖: + ```bash + pip install progress + ``` + +7. 处理缺少模块: + ```bash + pip install pyyaml # No module named 'yaml' + pip install torch_geometric + pip install hnswlib + pip install intervaltree + pip install annoy + pip install pyg_lib torch_scatter torch_sparse torch_cluster torch_spline_conv -f https://data.pyg.org/whl/torch-2.4.0+cu121.html + pip install POT # No module named 'ot' + pip install dgl -f https://data.dgl.ai/wheels/torch-2.4/cu121/repo.html + ``` + +8. 再次查看已安装包,确认 torch 版本: + ```bash + pip list + ``` + > 可以看到 torch 版本已经变成 2.4.0。 + +9. 安装 R 环境: + ```bash + conda install r-base # 安装 rpy2 前先用 conda 安装 R 语言环境 + ``` + +10. 进入 R 语言环境,安装 mclust 包: + ```R + R + install.packages("mclust") # 随便选一个源,我选的是 20 + q() # 退出 R 语言环境 + ``` + +11. 安装 rpy2: + ```bash + pip install rpy2 + ``` + +12. 至此,可以运行以下链接成功: + - [T1_DLPFC](https://stagate.readthedocs.io/en/latest/T1_DLPFC.html) + +13. 安装 louvain: + ```bash + pip install louvain + ``` + +14. 至此,可以运行以下链接成功: + - [T4_Stereo](https://stagate.readthedocs.io/en/latest/T4_Stereo.html) + +15. 运行以下链接: + - [Tutorial_STABox_STAligner](https://stabox-tutorial.readthedocs.io/en/latest/Tutorial_STABox_STAligner.html) + +16. 图形界面需要额外安装以下包: + ```bash + pip install ttkbootstrap + pip install opencv-python + pip install upsetplot + pip install gseapy + ``` + +17. 本地安装端口转发工具 XLaunch,把服务器端图形界面 export display 到本地电脑,通常会有些卡顿: + ```bash + cd STABox/src + python -m stabox.view.app + ``` + +> 至此,STABOX 界面可以启动成功。 +具体 pip 环境见 requirement.txt 文件。 +``` \ No newline at end of file diff --git a/STABox/Renv_setting.yaml b/STABox/Renv_setting.yaml deleted file mode 100644 index 5e297a0..0000000 --- a/STABox/Renv_setting.yaml +++ /dev/null @@ -1,2 +0,0 @@ -R_HOME: D:\\Users\\lqlu\\work\\software\\R-4.2.1 -R_USER: D:\\Users\\lqlu\\work\\software\\Anaconda\\envs\\STAKITS\\Lib\\site-packages\\rpy2 diff --git a/STABox/src/Stereo-seq_mouse.ipynb b/STABox/src/Stereo-seq_mouse.ipynb new file mode 100644 index 0000000..5cde843 --- /dev/null +++ b/STABox/src/Stereo-seq_mouse.ipynb @@ -0,0 +1,304 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import warnings\n", + "warnings.filterwarnings(\"ignore\")\n", + "import pandas as pd\n", + "import numpy as np\n", + "import scanpy as sc\n", + "import matplotlib.pyplot as plt\n", + "import os\n", + "import sys\n", + "import time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stabox.model import STAGATE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "counts_file = os.path.join('/mnt/disk1/LZJ/project/STABox/STABox_Data/Stero-seq/Dataset1_LiuLongQi_MouseOlfactoryBulb/Data/RNA_counts.tsv')\n", + "coor_file = os.path.join('/mnt/disk1/LZJ/project/STABox/STABox_Data/Stero-seq/Dataset1_LiuLongQi_MouseOlfactoryBulb/position.tsv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "counts = pd.read_csv(counts_file, sep='\\t', index_col=0)\n", + "coor_df = pd.read_csv(coor_file, sep='\\t')\n", + "print(counts.shape, coor_df.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "counts.columns = ['Spot_'+str(x) for x in counts.columns]\n", + "coor_df.index = coor_df['label'].map(lambda x: 'Spot_'+str(x))\n", + "coor_df = coor_df.loc[:, ['x','y']]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "coor_df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "adata = sc.AnnData(counts.T)\n", + "adata.var_names_make_unique()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "adata" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "coor_df = coor_df.loc[adata.obs_names, ['y', 'x']]\n", + "adata.obsm[\"spatial\"] = coor_df.to_numpy()\n", + "sc.pp.calculate_qc_metrics(adata, inplace=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.rcParams[\"figure.figsize\"] = (5,4)\n", + "sc.pl.embedding(adata, basis=\"spatial\", color=\"n_genes_by_counts\", show=False)\n", + "plt.title(\"\")\n", + "plt.axis('off')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "used_barcode = pd.read_csv(os.path.join('/mnt/disk1/LZJ/project/STABox/STABox_Data/Stero-seq/Dataset1_LiuLongQi_MouseOlfactoryBulb/used_barcodes.txt'), sep='\\t', header=None)\n", + "used_barcode = used_barcode[0]\n", + "adata = adata[used_barcode,]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.rcParams[\"figure.figsize\"] = (5,4)\n", + "sc.pl.embedding(adata, basis=\"spatial\", color=\"n_genes_by_counts\", show=False)\n", + "plt.title(\"\")\n", + "plt.axis('off')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sc.pp.filter_genes(adata, min_cells=50)\n", + "print('After flitering: ', adata.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#Normalization\n", + "sc.pp.highly_variable_genes(adata, flavor=\"seurat_v3\", n_top_genes=3000)\n", + "sc.pp.normalize_total(adata, target_sum=1e4)\n", + "sc.pp.log1p(adata)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from stabox.model._utils import Cal_Spatial_Net, Stats_Spatial_Net" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Cal_Spatial_Net(adata, rad_cutoff=50)\n", + "Stats_Spatial_Net(adata)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stagate_ = STAGATE(model_dir=\"/mnt/disk1/LZJ/project/STABox/lzj/LZJ/project/STABox/STABox_Data/Stero-seq\", in_features=3000, hidden_dims=[512, 30])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "adata=stagate_.train(adata)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "adata=stagate_.train_subgraph(adata)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sc.pp.neighbors(adata, use_rep='STAGATE')\n", + "sc.tl.umap(adata)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sc.tl.louvain(adata, resolution=0.8)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.rcParams[\"figure.figsize\"] = (3, 3)\n", + "sc.pl.embedding(adata, basis=\"spatial\", color=\"louvain\",s=6, show=False, title='STAGATE')\n", + "plt.axis('off')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sc.pl.umap(adata, color='louvain', title='STAGATE')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sc.pp.pca(adata, n_comps=30)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sc.pp.neighbors(adata, use_rep='X_pca')\n", + "sc.tl.louvain(adata, resolution=0.8)\n", + "sc.tl.umap(adata)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.rcParams[\"figure.figsize\"] = (3, 3)\n", + "sc.pl.embedding(adata, basis=\"spatial\", color=\"louvain\",s=6, show=False, title='SCANPY')\n", + "plt.axis('off')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sc.pl.umap(adata, color='louvain', title='SCANPY')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "stabox", + "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.10.14" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/STABox/src/stabox/model/stagate.py b/STABox/src/stabox/model/stagate.py index 9bf271a..df66446 100644 --- a/STABox/src/stabox/model/stagate.py +++ b/STABox/src/stabox/model/stagate.py @@ -10,7 +10,9 @@ import scanpy as sc import scipy.sparse as sp import os - +import time +import random +from torch_geometric.loader import ClusterData, ClusterLoader class STAGATE(BaseModelMixin): SUPPORTED_TASKS = ["tissue_structure_annotation", "spatial_embedding", "enhanced_gene_expression", @@ -107,4 +109,107 @@ def load(self, path, **kwargs): self.model_name='STAGATE' model_path = os.path.join(path, self.model_name + '_model.pth') model = self.model.load_state_dict(torch.load(model_path)) - return model \ No newline at end of file + return model + + def train_subgraph(self, adata, hidden_dims=[512, 30], n_epochs=1000, lr=0.001, key_added='STAGATE', + gradient_clipping=5., weight_decay=0.0001, verbose=True, + random_seed=0, save_loss=False, save_reconstrction=False, + device=torch.device('cuda:0' if torch.cuda.is_available() else 'cpu'),num_parts=128,batch_size=16,num_workers=0,**kwargs): + # Set random seeds for reproducibility + seed = random_seed + random.seed(seed) + torch.manual_seed(seed) + np.random.seed(seed) + if torch.cuda.is_available(): + torch.cuda.manual_seed_all(seed) + + # Ensure sparse matrix format + adata.X = sp.csr_matrix(adata.X) + + # Filter data for highly variable genes if available + if 'highly_variable' in adata.var.columns: + adata_Vars = adata[:, adata.var['highly_variable']] + else: + adata_Vars = adata + + if verbose: + print('Size of Input: ', adata_Vars.shape) + + # Ensure that Spatial_Net is calculated before running + if 'Spatial_Net' not in adata.uns.keys(): + raise ValueError("Spatial_Net does not exist! Run Cal_Spatial_Net first!") + + # Prepare the data for training + data = self.prepare_data(adata_Vars) + + # Initialize the model + model = STAGateModule(self.in_features, hidden_dims).to(device) + + # Reset CUDA peak memory stats and log initial memory usage + torch.cuda.reset_peak_memory_stats() + print(f"Initial Peak Memory: {torch.cuda.max_memory_allocated() / 1024**2:.2f} MB") + + # Print the number of model parameters + print('Number of parameters: ', sum(p.numel() for p in model.parameters())) + + # Create clusters (subgraphs) + cluster_data = ClusterData(data, num_parts) + train_loader = ClusterLoader(cluster_data, batch_size=batch_size, shuffle=True, num_workers=num_workers, pin_memory=True) + + # Ensure the total number of nodes in the subgraphs equals the number of nodes in the full graph + total_num_nodes, total_num_edges = 0, 0 + for step, sub_data in enumerate(train_loader): + print(f"Step {step+1}") + print(f"Subgraph Node Count: {sub_data.num_nodes}, Subgraph Edge Count: {sub_data.num_edges}") + total_num_nodes += sub_data.num_nodes + total_num_edges += sub_data.num_edges + + print(f"Total Nodes: {total_num_nodes}, Full Graph Nodes: {data.num_nodes}, Total Edges: {total_num_edges}, Full Graph Edges: {data.num_edges}") + assert total_num_nodes == data.num_nodes, "The number of nodes in subgraphs is not equal to the number of nodes in the full graph!" + + # Set up the optimizer + optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=weight_decay) + + start_time=time.time() + for epoch in tqdm(range(1, n_epochs + 1)): + model.train() + for step,sub_data in enumerate(train_loader): + sub_data = sub_data.to(device) + optimizer.zero_grad() + z, out = model(sub_data.x, sub_data.edge_index) + # Calculate loss and backpropagate + loss = F.mse_loss(sub_data.x, out) + loss.backward() + # Apply gradient clipping + torch.nn.utils.clip_grad_norm_(model.parameters(), gradient_clipping) + # Update model parameters + optimizer.step() + + # Set the model to evaluation mode and move it to CPU for final inference + model.eval() + model = model.to('cpu') + + # Perform inference on the full graph (CPU) + with torch.no_grad(): + data = data.to('cpu') + z, out = model(data.x, data.edge_index) + + # Print the final peak memory usage + print(f"Final Peak Memory: {torch.cuda.max_memory_allocated() / 1024**2:.2f} MB") + + # Save the model outputs and other results to adata + STAGATE_rep = z.to('cpu').detach().numpy() + adata.obsm[key_added] = STAGATE_rep + self.model = model + + # Save loss if requested + if save_loss: + adata.uns['STAGATE_loss'] = loss.item() + + # Save reconstruction if requested + if save_reconstrction: + ReX = out.to('cpu').detach().numpy() + ReX[ReX < 0] = 0 # Ensure non-negative values for reconstruction + adata.layers['STAGATE_ReX'] = ReX + + return adata \ No newline at end of file diff --git a/STABox/src/stabox/view/main.py b/STABox/src/stabox/view/main.py index 5fa447c..e89c453 100644 --- a/STABox/src/stabox/view/main.py +++ b/STABox/src/stabox/view/main.py @@ -1,11 +1,7 @@ import random -import re import subprocess import warnings import sys -# from concurrent.futures import ThreadPoolExecutor -# from typing import Callable -# from tqdm import tqdm import matplotlib import tkinter as tk import cv2 @@ -14,14 +10,15 @@ from scipy.sparse import issparse, csr_matrix import anndata import yaml + sys.path.append("..") -plt.rc('font', family='Arial') +plt.rc("font", family="Arial") from upsetplot import plot, from_contents import gseapy as gp from gseapy import barplot, dotplot -matplotlib.use('Agg') +matplotlib.use("Agg") warnings.filterwarnings("ignore") from datetime import datetime import ttkbootstrap as ttk @@ -32,6 +29,7 @@ from ttkbootstrap import Style from pathlib import Path import threading +import concurrent.futures import queue import shutil @@ -49,7 +47,15 @@ import scipy.linalg import torch import anndata as ad -from ..pl.utils import Cal_Spatial_Net, Stats_Spatial_Net, Cal_Spatial_Net_3D, mclust_R, Cal_Spatial_Net_new, parse_args, select_svgs +from ..pl.utils import ( + Cal_Spatial_Net, + Stats_Spatial_Net, + Cal_Spatial_Net_3D, + mclust_R, + Cal_Spatial_Net_new, + parse_args, + select_svgs, +) from ..model import STAligner from ..model import STAMarker from ..extension.STAGE import STAGE @@ -65,11 +71,14 @@ import tkinter import tkinter.ttk as ttks from tkinter import messagebox + seed = 666 import torch.backends.cudnn as cudnn + cudnn.deterministic = True cudnn.benchmark = True import random + random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) @@ -78,33 +87,53 @@ global data_type global image_files image_files = { - 'properties-dark': 'icons8_settings_24px.png', - 'properties-light': 'icons8_settings_24px_2.png', - 'add-to-backup-dark': 'icons8_add_folder_24px.png', - 'add-to-backup-light': 'icons8_add_book_24px.png', - 'stop-backup-dark': 'icons8_cancel_24px.png', - 'stop-backup-light': 'icons8_cancel_24px_1.png', - 'play': 'icons8_play_24px_1.png', - 'refresh': 'icons8_refresh_24px_1.png', - 'stop-dark': 'icons8_stop_24px.png', - 'stop-light': 'icons8_stop_24px_1.png', - 'opened-folder': 'icons8_opened_folder_24px.png', - 'data_add': 'icons8_opened_folder_24px_1.png', - 'logo': 'backup.png' + "properties-dark": "icons8_settings_24px.png", + "properties-light": "icons8_settings_24px_2.png", + "add-to-backup-dark": "icons8_add_folder_24px.png", + "add-to-backup-light": "icons8_add_book_24px.png", + "stop-backup-dark": "icons8_cancel_24px.png", + "stop-backup-light": "icons8_cancel_24px_1.png", + "play": "icons8_play_24px_1.png", + "refresh": "icons8_refresh_24px_1.png", + "stop-dark": "icons8_stop_24px.png", + "stop-light": "icons8_stop_24px_1.png", + "opened-folder": "icons8_opened_folder_24px.png", + "data_add": "icons8_opened_folder_24px_1.png", + "logo": "backup.png", } -methods = ['STAGATE', 'STAligner', 'STAMarker', 'STAGE', 'SpaGCN', 'SEDR', 'SCANPY', 'STAMapper', 'STALocator'] -data_type = ['10x', 'Slide-seqV2', 'Stereo-seq', 'MERFISH', 'Slide-seq', 'ST', 'STARmap', 'HDST', 'H5AD-files', - 'Multi-files'] - -PATH = Path(__file__).parent / 'assets' +methods = [ + "STAGATE", + "STAligner", + "STAMarker", + "STAGE", + "SpaGCN", + "SEDR", + "SCANPY", + "STAMapper", + "STALocator", +] +data_type = [ + "10x", + "Slide-seqV2", + "Stereo-seq", + "MERFISH", + "Slide-seq", + "ST", + "STARmap", + "HDST", + "H5AD-files", + "Multi-files", +] + +PATH = Path(__file__).parent / "assets" Raw_PATH = Path(__file__).parent current_file_path = os.path.abspath(__file__) test_file_path = os.path.dirname(current_file_path) running_path = os.path.dirname(test_file_path) -print(f'running_path={running_path}') -print(f'current_file_path={current_file_path}') -print(f'test_file_path={test_file_path}') +print(f"running_path={running_path}") +print(f"current_file_path={current_file_path}") +print(f"test_file_path={test_file_path}") class Tooltip: @@ -175,84 +204,101 @@ def __init__(self, master=None, *args, **kwargs): self.result_queue = queue.Queue() self.flag_queue = queue.Queue() - self.method_flag = '' + self.method_flag = "" self.trained_file_path = None self.photoimages = [] self.GUI() + self.load_setting() + + def load_setting(self): + path = "../Renv_setting.yaml" + if os.path.exists(path): + with open(path, "r") as f: + yaml_data = yaml.safe_load(f) + os.environ["R_HOME"] = yaml_data["R_HOME"] + os.environ["R_USER"] = yaml_data["R_USER"] + messagebox.showinfo( + "Settings Loaded", + f'''R_HOME has been set to: \n {yaml_data["R_HOME"]} \nR_USER has been set to: {os.environ["R_USER"]}''', + ) + else: + messagebox.showerror("Error", "Make sure the YAML file exists! Or You can set it manually in the setting.") + def GUI(self): # imgpath = 'VIEW/assets' - imgpath = test_file_path + '/assets' + imgpath = test_file_path + "/assets" for key, val in image_files.items(): - _path = imgpath + '/' + val + _path = imgpath + "/" + val self.photoimages.append(ttk.PhotoImage(name=key, file=_path)) - buttonbar = ttk.Frame(self, style='primary.TFrame') + buttonbar = ttk.Frame(self, style="primary.TFrame") buttonbar.pack(fill=X, pady=1, side=TOP) sty = ttk.Style() - sty.configure('my.TButton', font="Arial") + sty.configure("my.TButton", font="Arial") self.downloadbtn = ttk.Button( master=buttonbar, - text='Download', - image='data_add', + text="Download", + image="data_add", compound=LEFT, - style='my.TButton', - command=self.data_download_GUI + style="my.TButton", + command=self.data_download_GUI, ) self.downloadbtn.pack(side=LEFT, ipadx=5, ipady=5, padx=0, pady=1) self.backup = ttk.Button( - master=buttonbar, text='Load', - image='add-to-backup-light', + master=buttonbar, + text="Load", + image="add-to-backup-light", compound=LEFT, - style='my.TButton', - command=self.Data_Preprocess_thread # self.Data_Preprocess_thread + style="my.TButton", + command=self.Data_Preprocess_thread, # self.Data_Preprocess_thread ) self.backup.pack(side=LEFT, ipadx=5, ipady=5, padx=(1, 0), pady=1) btn = ttk.Button( master=buttonbar, - text='Preprocess', - image='refresh', + text="Preprocess", + image="refresh", compound=LEFT, - style='my.TButton', - command=self.Preprocess + style="my.TButton", + command=self.Preprocess, ) btn.pack(side=LEFT, ipadx=5, ipady=5, padx=0, pady=1) btn = ttk.Button( master=buttonbar, - text='Run', - image='play', + text="Run", + image="play", compound=LEFT, - style='my.TButton', - command=self.Data_process + style="my.TButton", + command=self.Data_process, ) btn.pack(side=LEFT, ipadx=5, ipady=5, padx=0, pady=1) btn = ttk.Button( master=buttonbar, - text='Restart', - image='stop-light', + text="Restart", + image="stop-light", compound=LEFT, - style='my.TButton', - command=self.Restart + style="my.TButton", + command=self.Restart, ) btn.pack(side=LEFT, ipadx=5, ipady=5, padx=0, pady=1) btn = ttk.Button( master=buttonbar, - text='Settings', - image='properties-light', + text="Settings", + image="properties-light", compound=LEFT, - style='my.TButton', - command=self.settings + style="my.TButton", + command=self.settings, ) btn.pack(side=LEFT, ipadx=5, ipady=5, padx=0, pady=1) - self.left_panel = ttk.Frame(self, style='bg.TFrame') + self.left_panel = ttk.Frame(self, style="bg.TFrame") self.left_panel.pack(side=LEFT, fill=Y) self.bus_cf = CollapsingFrame(self.left_panel) @@ -262,17 +308,17 @@ def GUI(self): self.file_path_frm.columnconfigure(1, weight=2) self.bus_cf.add( child=self.file_path_frm, - font=('Arial', 10), - title='Load h5ad files', - bootstyle=SECONDARY + font=("Arial", 10), + title="Load h5ad files", + bootstyle=SECONDARY, ) self.path_load_flag = False style = Style() style.configure("TCheckbutton", font=("Arial", 10)) - style.configure('TButton', font=('Arial', 10)) - style.configure('TRadiobutton', font=('Arial', 10)) - style.configure('TCombobox', font=('Arial', 10)) + style.configure("TButton", font=("Arial", 10)) + style.configure("TRadiobutton", font=("Arial", 10)) + style.configure("TCombobox", font=("Arial", 10)) self.radio_frame = ttk.Frame(self.file_path_frm) self.radio_frame.pack(side=TOP) @@ -283,30 +329,32 @@ def on_radio_select(value): if value == "single-h5ad": self.Single_file_moduel = ttk.Frame(self.file_path_frm) self.Single_file_moduel.pack(after=self.radio_frame) - self.file_entry = ttk.Entry(self.Single_file_moduel, textvariable='folder-path', font="Arial") + self.file_entry = ttk.Entry( + self.Single_file_moduel, textvariable="folder-path", font="Arial" + ) self.file_entry.pack(side=LEFT, fill=X, expand=YES) - self.file_entry.insert(END, 'select your datas here!') + self.file_entry.insert(END, "select your datas here!") def set_data_type_choose(event): - print('Current choose: {}'.format(self.data_updata.get())) + print("Current choose: {}".format(self.data_updata.get())) self.data_type = self.data_updata.get() # select_data_type = ttk.StringVar() self.data_updata = ttk.Combobox( master=self.Single_file_moduel, - textvariable='select_data_type', - font=('Arial', 10), + textvariable="select_data_type", + font=("Arial", 10), values=data_type, height=8, width=6, - state='normal', - cursor='plus', + state="normal", + cursor="plus", ) self.data_updata.pack(side=LEFT) - self.setvar('select_data_type', data_type[0]) + self.setvar("select_data_type", data_type[0]) # self.data_updata.current(0) - self.data_updata.bind('<>', set_data_type_choose) + self.data_updata.bind("<>", set_data_type_choose) def file_btn_getdirectory(): self.path_load_flag = False @@ -314,9 +362,9 @@ def file_btn_getdirectory(): self.file_btn = ttk.Button( master=self.Single_file_moduel, - image='opened-folder', + image="opened-folder", bootstyle=(LINK, SECONDARY), - command=file_btn_getdirectory + command=file_btn_getdirectory, ) self.file_btn.pack(side=RIGHT) self.path_load_flag = True @@ -324,7 +372,9 @@ def file_btn_getdirectory(): self.Single_file_moduel = ttk.Frame(self.file_path_frm) self.Single_file_moduel.pack(after=self.radio_frame) - file_entry = ttk.Entry(self.Single_file_moduel, textvariable='folder-path') + file_entry = ttk.Entry( + self.Single_file_moduel, textvariable="folder-path" + ) file_entry.pack(side=LEFT, fill=X, expand=YES) def Select_files(): @@ -334,34 +384,48 @@ def Select_files(): self.path_load_flag = False self.Select_files() - file_choose_btn = ttk.Button(master=self.Single_file_moduel, text="Choose", width=6, - command=Select_files) + file_choose_btn = ttk.Button( + master=self.Single_file_moduel, + text="Choose", + width=6, + command=Select_files, + ) file_choose_btn.pack(side=RIGHT) self.path_load_flag = True radio_var = tk.StringVar() - radio1 = ttk.Radiobutton(self.radio_frame, text="Analysis single h5ad file", style="TCheckbutton", - variable=radio_var, value="single-h5ad", - command=lambda: on_radio_select("single-h5ad")) + radio1 = ttk.Radiobutton( + self.radio_frame, + text="Analysis single h5ad file", + style="TCheckbutton", + variable=radio_var, + value="single-h5ad", + command=lambda: on_radio_select("single-h5ad"), + ) radio1.grid(row=0, column=0, padx=5, pady=5, sticky="w") - radio2 = ttk.Radiobutton(self.radio_frame, text="Analysis Multi-h5ad files", style="TCheckbutton", - variable=radio_var, value="multi h5ad", - command=lambda: on_radio_select("Multi-h5ad")) + radio2 = ttk.Radiobutton( + self.radio_frame, + text="Analysis Multi-h5ad files", + style="TCheckbutton", + variable=radio_var, + value="multi h5ad", + command=lambda: on_radio_select("Multi-h5ad"), + ) radio2.grid(row=1, column=0, padx=5, pady=5, sticky="w") self.bus_frm = ttk.Frame(self.bus_cf, padding=10) self.bus_frm.columnconfigure(1, weight=2) self.bus_cf.add( child=self.bus_frm, - font=('Arial', 10), - title='Select Methods', - bootstyle=SECONDARY + font=("Arial", 10), + title="Select Methods", + bootstyle=SECONDARY, ) self.frames = ttk.Frame(self.bus_frm) self.frames.pack(side=TOP, anchor=W) def set_value_before_choose(): - print('Methods:', select_text_data.get()) + print("Methods:", select_text_data.get()) new_select_data = [] for i in methods: if select_text_data.get() in i: @@ -372,13 +436,13 @@ def set_value_before_choose(): self.select_box_obj = ttk.Combobox( master=self.frames, textvariable=select_text_data, - font=('Arial', 10), + font=("Arial", 10), values=methods, height=8, width=20, - state='normal', - cursor='plus', - postcommand=set_value_before_choose + state="normal", + cursor="plus", + postcommand=set_value_before_choose, ) self.select_box_obj.pack(side=LEFT, padx=20, anchor=W) self.select_box_obj.current(0) @@ -422,79 +486,110 @@ def train_epoch_choose(): def referance_adjust(): try: self.p_frame = tk.Frame(master=self.bus_frm) - self.p_frame.pack(fill=ttk.BOTH, expand=True, side=BOTTOM, anchor=W, padx=20, pady=10) - self.label = ttk.Label(self.p_frame, text='Parameter setting: ', width=25) + self.p_frame.pack( + fill=ttk.BOTH, expand=True, side=BOTTOM, anchor=W, padx=20, pady=10 + ) + self.label = ttk.Label( + self.p_frame, text="Parameter setting: ", width=25 + ) self.label.pack(side=TOP, anchor=W, pady=10) - self.para_frame = tk.Frame(master=self.p_frame, highlightbackground="black", highlightthickness=1) + self.para_frame = tk.Frame( + master=self.p_frame, + highlightbackground="black", + highlightthickness=1, + ) self.para_frame.pack(side=BOTTOM, anchor=W, pady=10) style = Style() style.configure("TCheckbutton", font=("Arial", 10)) - style.configure('TButton', font=('Arial', 10)) + style.configure("TButton", font=("Arial", 10)) self.btn_states = False - if self.method_flag == 'STAGATE': + if self.method_flag == "STAGATE": self.rad_cutoff_value = int(150) self.alpha_value = int(3000) self.cluster_value = int(1000) self.genes = float(0.001) self.detail_info = "Deciphering spatial domains" - self.rad_cutoff_info = ttk.Label(master=self.para_frame, text="Neighbor distance", font="Arial") - self.rad_cutoff_info.grid(row=1, column=0, padx=20, pady=10, sticky="nsew") + self.rad_cutoff_info = ttk.Label( + master=self.para_frame, text="Neighbor distance", font="Arial" + ) + self.rad_cutoff_info.grid( + row=1, column=0, padx=20, pady=10, sticky="nsew" + ) self.rad_cutoff = ttk.Entry( master=self.para_frame, - textvariable='rad_cutoff', + textvariable="rad_cutoff", validate="focusout", validatecommand=cutoff_num_check, - width=20 + width=20, ) self.rad_cutoff.grid(row=1, column=1, padx=20, pady=10) - self.setvar('rad_cutoff', int(150)) - self.alpha_info = ttk.Label(master=self.para_frame, text="Features dimension ", font="Arial") - self.alpha_info.grid(row=2, column=0, padx=20, pady=10, sticky="nsew") + self.setvar("rad_cutoff", int(150)) + self.alpha_info = ttk.Label( + master=self.para_frame, text="Features dimension ", font="Arial" + ) + self.alpha_info.grid( + row=2, column=0, padx=20, pady=10, sticky="nsew" + ) self.alpha = ttk.Entry( master=self.para_frame, - textvariable='features', + textvariable="features", validate="focusout", validatecommand=alpha_num_check, - width=20 + width=20, ) self.alpha.grid(row=2, column=1, padx=20, pady=10) - self.setvar('features', int(3000)) - self.cluster_info = ttk.Label(master=self.para_frame, text="Train epochs", font="Arial") - self.cluster_info.grid(row=3, column=0, padx=20, pady=10, sticky="nsew") + self.setvar("features", int(3000)) + self.cluster_info = ttk.Label( + master=self.para_frame, text="Train epochs", font="Arial" + ) + self.cluster_info.grid( + row=3, column=0, padx=20, pady=10, sticky="nsew" + ) self.cluster = ttk.Entry( master=self.para_frame, - textvariable='epochs', + textvariable="epochs", validate="focusout", validatecommand=cluster_num_check, - width=20 + width=20, ) self.cluster.grid(row=3, column=1, padx=20, pady=10) - self.setvar('epochs', int(1000)) - self.genes_info = ttk.Label(master=self.para_frame, text="Learning rate", font="Arial") - self.genes_info.grid(row=4, column=0, padx=20, pady=10, sticky="nsew") + self.setvar("epochs", int(1000)) + self.genes_info = ttk.Label( + master=self.para_frame, text="Learning rate", font="Arial" + ) + self.genes_info.grid( + row=4, column=0, padx=20, pady=10, sticky="nsew" + ) self.gene_name = ttk.Entry( master=self.para_frame, - textvariable='learning rate', + textvariable="learning rate", validate="focusout", validatecommand=gene_name_check, - width=20 + width=20, ) self.gene_name.grid(row=4, column=1, padx=20, pady=10) - self.setvar('learning rate', float(0.001)) - self.detail_infos = ttk.Label(master=self.para_frame, text="Details", font="Arial") - self.detail_infos.grid(row=5, column=0, padx=20, pady=10, sticky="nsew") + self.setvar("learning rate", float(0.001)) + self.detail_infos = ttk.Label( + master=self.para_frame, text="Details", font="Arial" + ) + self.detail_infos.grid( + row=5, column=0, padx=20, pady=10, sticky="nsew" + ) self.detail_info_box = ttk.Entry( master=self.para_frame, - textvariable='detail_info', + textvariable="detail_info", validate="focusout", validatecommand=detail_info_check, - width=20 + width=20, ) self.detail_info_box.grid(row=5, column=1, padx=20, pady=10) - self.setvar('detail_info', "Deciphering spatial domains") - Tooltip(self.rad_cutoff, "Distance threshold between center spot and neighbors: 10X-150") + self.setvar("detail_info", "Deciphering spatial domains") + Tooltip( + self.rad_cutoff, + "Distance threshold between center spot and neighbors: 10X-150", + ) Tooltip(self.alpha, "Dimensions of embedding genes: 3000") Tooltip(self.cluster, "Training epochs number: 1000") Tooltip(self.gene_name, "Learning rate: 0.001") @@ -502,84 +597,119 @@ def referance_adjust(): method_btn.configure(state=DISABLED) - self.information = 'Deep learning' - self.functions = 'Deciphering spatial domains' - self.Run_time = '3-5 mins' + self.information = "Deep learning" + self.functions = "Deciphering spatial domains" + self.Run_time = "3-5 mins" self.Datatime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") style_head = ttk.Style() style_head.configure("Treeview.Heading", font="Arial") - self.tv.insert('', END, - values=(self.method_flag, - self.information, self.functions, self.Run_time, - self.Datatime)) + self.tv.insert( + "", + END, + values=( + self.method_flag, + self.information, + self.functions, + self.Run_time, + self.Datatime, + ), + ) - elif self.method_flag == 'STAligner': + elif self.method_flag == "STAligner": self.rad_cutoff_value = int(150) self.adjust_value = int(1) self.cluster_value = int(1000) self.alpha_value = float(0.001) - self.detail_info = "Alignment and integration of spatially transcriptomes" - self.rad_cutoff_info = ttk.Label(master=self.para_frame, text="Neighbor distance", font="Arial") - self.rad_cutoff_info.grid(row=1, column=0, padx=20, pady=10, sticky="nsew") + self.detail_info = ( + "Alignment and integration of spatially transcriptomes" + ) + self.rad_cutoff_info = ttk.Label( + master=self.para_frame, text="Neighbor distance", font="Arial" + ) + self.rad_cutoff_info.grid( + row=1, column=0, padx=20, pady=10, sticky="nsew" + ) self.rad_cutoff = ttk.Entry( master=self.para_frame, - textvariable='rad_cutoff', + textvariable="rad_cutoff", validate="focusout", validatecommand=cutoff_num_check, - width=20 + width=20, ) self.rad_cutoff.grid(row=1, column=1, padx=20, pady=10) - self.setvar('rad_cutoff', int(150)) + self.setvar("rad_cutoff", int(150)) - self.cluster_info = ttk.Label(master=self.para_frame, text="Training epochs", font="Arial") - self.cluster_info.grid(row=2, column=0, padx=20, pady=10, sticky="nsew") + self.cluster_info = ttk.Label( + master=self.para_frame, text="Training epochs", font="Arial" + ) + self.cluster_info.grid( + row=2, column=0, padx=20, pady=10, sticky="nsew" + ) self.cluster = ttk.Entry( master=self.para_frame, - textvariable='n_epochs', + textvariable="n_epochs", validate="focusout", validatecommand=cluster_num_check, - width=20 + width=20, ) self.cluster.grid(row=2, column=1, padx=20, pady=10) - self.setvar('n_epochs', int(1000)) + self.setvar("n_epochs", int(1000)) - self.adjust_info = ttk.Label(master=self.para_frame, text="Slice margin", font="Arial") - self.adjust_info.grid(row=3, column=0, padx=20, pady=10, sticky="nsew") + self.adjust_info = ttk.Label( + master=self.para_frame, text="Slice margin", font="Arial" + ) + self.adjust_info.grid( + row=3, column=0, padx=20, pady=10, sticky="nsew" + ) self.adjust = ttk.Entry( master=self.para_frame, - textvariable='margin', + textvariable="margin", validate="focusout", validatecommand=adjust_num_check, - width=20 + width=20, ) self.adjust.grid(row=3, column=1, padx=20, pady=10) - self.setvar('margin', int(1)) + self.setvar("margin", int(1)) - self.alpha_info = ttk.Label(master=self.para_frame, text="Learning rate", font="Arial") - self.alpha_info.grid(row=4, column=0, padx=20, pady=10, sticky="nsew") + self.alpha_info = ttk.Label( + master=self.para_frame, text="Learning rate", font="Arial" + ) + self.alpha_info.grid( + row=4, column=0, padx=20, pady=10, sticky="nsew" + ) self.alpha = ttk.Entry( master=self.para_frame, - textvariable='learning rate', + textvariable="learning rate", validate="focusout", validatecommand=alpha_num_check, - width=20 + width=20, ) self.alpha.grid(row=4, column=1, padx=20, pady=10) - self.setvar('learning rate', float(0.001)) + self.setvar("learning rate", float(0.001)) - self.detail_infos = ttk.Label(master=self.para_frame, text="Details", font="Arial") - self.detail_infos.grid(row=5, column=0, padx=20, pady=10, sticky="nsew") + self.detail_infos = ttk.Label( + master=self.para_frame, text="Details", font="Arial" + ) + self.detail_infos.grid( + row=5, column=0, padx=20, pady=10, sticky="nsew" + ) self.detail_info_box = ttk.Entry( master=self.para_frame, - textvariable='detail_info', + textvariable="detail_info", validate="focusout", validatecommand=detail_info_check, - width=20 + width=20, ) self.detail_info_box.grid(row=5, column=1, padx=20, pady=10) - self.setvar('detail_info', "Alignment and integration of spatially transcriptomes") + self.setvar( + "detail_info", + "Alignment and integration of spatially transcriptomes", + ) - Tooltip(self.rad_cutoff, "Distance threshold between center spot and neighbors: 10X-150") + Tooltip( + self.rad_cutoff, + "Distance threshold between center spot and neighbors: 10X-150", + ) Tooltip(self.cluster, "Training epochs number: 1000") Tooltip(self.adjust, "Slice alignment hyperparameter: 1") Tooltip(self.alpha, "learning rate: 0.001") @@ -587,100 +717,136 @@ def referance_adjust(): method_btn.configure(state=DISABLED) - self.information = 'Deep learning' - self.functions = 'Alignment and integration of spatially transcriptomes' - self.Run_time = '5-10 mins' + self.information = "Deep learning" + self.functions = ( + "Alignment and integration of spatially transcriptomes" + ) + self.Run_time = "5-10 mins" self.Authods = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - self.tv.insert('', END, - values=(self.method_flag, - self.information, self.functions, self.Run_time, - self.Authods)) + self.tv.insert( + "", + END, + values=( + self.method_flag, + self.information, + self.functions, + self.Run_time, + self.Authods, + ), + ) - elif self.method_flag == 'STAMarker': + elif self.method_flag == "STAMarker": self.rad_cutoff_value = int(150) self.alpha_value = int(5) self.cluster_value = int(7) self.train_epoch_num = int(500) self.cla_epoch_num = int(500) self.detail_info = "Deciphering spatial domains SVGs" - self.rad_cutoff_info = ttk.Label(master=self.para_frame, text="Neighbor distance", font="Arial") - self.rad_cutoff_info.grid(row=1, column=0, padx=20, pady=10, sticky="nsew") + self.rad_cutoff_info = ttk.Label( + master=self.para_frame, text="Neighbor distance", font="Arial" + ) + self.rad_cutoff_info.grid( + row=1, column=0, padx=20, pady=10, sticky="nsew" + ) self.rad_cutoff = ttk.Entry( master=self.para_frame, - textvariable='rad_cutoff', + textvariable="rad_cutoff", validate="focusout", validatecommand=cutoff_num_check, - width=20 + width=20, ) self.rad_cutoff.grid(row=1, column=1, padx=20, pady=10) - self.setvar('rad_cutoff', int(150)) + self.setvar("rad_cutoff", int(150)) - self.alpha_info = ttk.Label(master=self.para_frame, text="Autoencoder number", font="Arial") - self.alpha_info.grid(row=2, column=0, padx=20, pady=10, sticky="nsew") + self.alpha_info = ttk.Label( + master=self.para_frame, text="Autoencoder number", font="Arial" + ) + self.alpha_info.grid( + row=2, column=0, padx=20, pady=10, sticky="nsew" + ) self.alpha = ttk.Entry( master=self.para_frame, - textvariable='autoencoder', + textvariable="autoencoder", validate="focusout", validatecommand=alpha_num_check, - width=20 + width=20, ) self.alpha.grid(row=2, column=1, padx=20, pady=10) - self.setvar('autoencoder', int(5)) + self.setvar("autoencoder", int(5)) - self.cluster_info = ttk.Label(master=self.para_frame, text="Cluster number", font="Arial") - self.cluster_info.grid(row=3, column=0, padx=20, pady=10, sticky="nsew") + self.cluster_info = ttk.Label( + master=self.para_frame, text="Cluster number", font="Arial" + ) + self.cluster_info.grid( + row=3, column=0, padx=20, pady=10, sticky="nsew" + ) self.cluster = ttk.Entry( master=self.para_frame, - textvariable='cluster', + textvariable="cluster", validate="focusout", validatecommand=cluster_num_check, - width=20 + width=20, ) self.cluster.grid(row=3, column=1, padx=20, pady=10) - self.setvar('cluster', int(7)) + self.setvar("cluster", int(7)) - self.train_epoch_info = ttk.Label(master=self.para_frame, text="Training epochs", font="Arial") - self.train_epoch_info.grid(row=4, column=0, padx=20, pady=10, sticky="nsew") + self.train_epoch_info = ttk.Label( + master=self.para_frame, text="Training epochs", font="Arial" + ) + self.train_epoch_info.grid( + row=4, column=0, padx=20, pady=10, sticky="nsew" + ) self.train_epoch_box = ttk.Entry( master=self.para_frame, - textvariable='epochs', + textvariable="epochs", validate="focusout", validatecommand=train_epoch_choose, - width=20 + width=20, ) self.train_epoch_box.grid(row=4, column=1, padx=20, pady=10) - self.setvar('epochs', 500) + self.setvar("epochs", 500) - self.class_epoch_infos = ttk.Label(master=self.para_frame, text="Classifiers epochs", font="Arial") - self.class_epoch_infos.grid(row=5, column=0, padx=20, pady=10, sticky="nsew") + self.class_epoch_infos = ttk.Label( + master=self.para_frame, text="Classifiers epochs", font="Arial" + ) + self.class_epoch_infos.grid( + row=5, column=0, padx=20, pady=10, sticky="nsew" + ) self.class_epoch_box = ttk.Entry( master=self.para_frame, - textvariable='classifiers', + textvariable="classifiers", validate="focusout", validatecommand=class_epoch_choose, - width=20 + width=20, ) self.class_epoch_box.grid(row=5, column=1, padx=20, pady=10) - self.setvar('classifiers', 500) + self.setvar("classifiers", 500) - self.detail_infos = ttk.Label(master=self.para_frame, text="Details", font="Arial") - self.detail_infos.grid(row=6, column=0, padx=20, pady=10, sticky="nsew") + self.detail_infos = ttk.Label( + master=self.para_frame, text="Details", font="Arial" + ) + self.detail_infos.grid( + row=6, column=0, padx=20, pady=10, sticky="nsew" + ) self.detail_info_box = ttk.Entry( master=self.para_frame, - textvariable='detail_info', + textvariable="detail_info", validate="focusout", validatecommand=detail_info_check, - width=20 + width=20, ) self.detail_info_box.grid(row=6, column=1, padx=20, pady=10) - self.setvar('detail_info', "Deciphering spatial domains SVGs") + self.setvar("detail_info", "Deciphering spatial domains SVGs") - Tooltip(self.rad_cutoff, "Distance threshold between center spot and neighbors: 10X-150") + Tooltip( + self.rad_cutoff, + "Distance threshold between center spot and neighbors: 10X-150", + ) Tooltip(self.alpha, "Autoencoder number: 5") Tooltip(self.cluster, "Number of cluster labels: 7") Tooltip(self.train_epoch_box, "training epochs: 500") @@ -689,160 +855,225 @@ def referance_adjust(): method_btn.configure(state=DISABLED) - self.information = 'Deep learning' - self.functions = 'Deciphering spatial domains SVGs' - self.Run_time = '10-30 mins' + self.information = "Deep learning" + self.functions = "Deciphering spatial domains SVGs" + self.Run_time = "10-30 mins" self.Datatime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") style_head = ttk.Style() style_head.configure("Treeview.Heading", font="Arial") - self.tv.insert('', END, - values=(self.method_flag, - self.information, self.functions, self.Run_time, - self.Datatime)) + self.tv.insert( + "", + END, + values=( + self.method_flag, + self.information, + self.functions, + self.Run_time, + self.Datatime, + ), + ) - elif self.method_flag == 'STAGE': + elif self.method_flag == "STAGE": self.alpha_value = float(0.5) self.genes = int(2000) self.functions_choose = "recovery" self.detail_info = "Gene information enhancement and recovery" - self.alpha_info = ttk.Label(master=self.para_frame, text="Downsampling ratio", font="Arial") - self.alpha_info.grid(row=1, column=0, padx=20, pady=10, sticky="nsew") + self.alpha_info = ttk.Label( + master=self.para_frame, text="Downsampling ratio", font="Arial" + ) + self.alpha_info.grid( + row=1, column=0, padx=20, pady=10, sticky="nsew" + ) self.alpha = ttk.Entry( master=self.para_frame, - textvariable='alpha', + textvariable="alpha", validate="focusout", validatecommand=alpha_num_check, - width=20 + width=20, ) self.alpha.grid(row=1, column=1, padx=20, pady=10) - self.setvar('alpha', float(0.5)) + self.setvar("alpha", float(0.5)) - self.genes_info = ttk.Label(master=self.para_frame, text="Training epochs", font="Arial") - self.genes_info.grid(row=2, column=0, padx=20, pady=10, sticky="nsew") + self.genes_info = ttk.Label( + master=self.para_frame, text="Training epochs", font="Arial" + ) + self.genes_info.grid( + row=2, column=0, padx=20, pady=10, sticky="nsew" + ) self.gene_name = ttk.Entry( master=self.para_frame, - textvariable='train_epoch', + textvariable="train_epoch", validate="focusout", validatecommand=gene_name_check, - width=20 + width=20, ) self.gene_name.grid(row=2, column=1, padx=20, pady=10) - self.setvar('train_epoch', 2000) + self.setvar("train_epoch", 2000) - self.function_infos = ttk.Label(master=self.para_frame, text="Functions select", font="Arial") - self.function_infos.grid(row=3, column=0, padx=20, pady=10, sticky="nsew") + self.function_infos = ttk.Label( + master=self.para_frame, text="Functions select", font="Arial" + ) + self.function_infos.grid( + row=3, column=0, padx=20, pady=10, sticky="nsew" + ) self.function_box = ttk.Entry( master=self.para_frame, - textvariable='function_infos', + textvariable="function_infos", validate="focusout", validatecommand=functions_info_check, - width=20 + width=20, ) self.function_box.grid(row=3, column=1, padx=20, pady=10) - self.setvar('function_infos', "recovery") + self.setvar("function_infos", "recovery") - self.detail_infos = ttk.Label(master=self.para_frame, text="Details", font="Arial") - self.detail_infos.grid(row=4, column=0, padx=20, pady=10, sticky="nsew") + self.detail_infos = ttk.Label( + master=self.para_frame, text="Details", font="Arial" + ) + self.detail_infos.grid( + row=4, column=0, padx=20, pady=10, sticky="nsew" + ) self.detail_info_box = ttk.Entry( master=self.para_frame, - textvariable='detail_info', + textvariable="detail_info", validate="focusout", validatecommand=detail_info_check, - width=20 + width=20, ) self.detail_info_box.grid(row=4, column=1, padx=20, pady=10) - self.setvar('detail_info', "Gene information enhancement and recovery") + self.setvar( + "detail_info", "Gene information enhancement and recovery" + ) Tooltip(self.alpha, "Algorithm hyperparameter: 0.5/[0-1]") Tooltip(self.gene_name, "Training epoch number: 2000") - Tooltip(self.function_box, "Functions choose: generation, recovery, 3d_model") + Tooltip( + self.function_box, + "Functions choose: generation, recovery, 3d_model", + ) Tooltip(self.detail_info_box, "Editable information: STAGE") method_btn.configure(state=DISABLED) - self.information = 'Supervised learning-gene information enhancement' - self.functions = 'Gene expression prediction and tissue segmentation' - self.Run_time = '10-40 mins' + self.information = ( + "Supervised learning-gene information enhancement" + ) + self.functions = ( + "Gene expression prediction and tissue segmentation" + ) + self.Run_time = "10-40 mins" self.Datatime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") style_head = ttk.Style() style_head.configure("Treeview.Heading", font="Arial") - self.tv.insert('', END, - values=(self.method_flag, - self.information, self.functions, self.Run_time, - self.Datatime)) - elif self.method_flag == 'SpaGCN': + self.tv.insert( + "", + END, + values=( + self.method_flag, + self.information, + self.functions, + self.Run_time, + self.Datatime, + ), + ) + elif self.method_flag == "SpaGCN": self.rad_cutoff_value = int(49) self.alpha_value = int(200) self.cluster_value = int(7) self.genes = float(0.5) self.detail_info = "Deciphering spatial domains" - self.rad_cutoff_info = ttk.Label(master=self.para_frame, text="Training weight", font="Arial") - self.rad_cutoff_info.grid(row=1, column=0, padx=20, pady=10, sticky="nsew") + self.rad_cutoff_info = ttk.Label( + master=self.para_frame, text="Training weight", font="Arial" + ) + self.rad_cutoff_info.grid( + row=1, column=0, padx=20, pady=10, sticky="nsew" + ) self.rad_cutoff = ttk.Entry( master=self.para_frame, - textvariable='rad_cutoff', + textvariable="rad_cutoff", validate="focusout", validatecommand=cutoff_num_check, - width=20 + width=20, ) self.rad_cutoff.grid(row=1, column=1, padx=20, pady=10) - self.setvar('rad_cutoff', int(49)) + self.setvar("rad_cutoff", int(49)) - self.alpha_info = ttk.Label(master=self.para_frame, text="Training epochs", font="Arial") - self.alpha_info.grid(row=2, column=0, padx=20, pady=10, sticky="nsew") + self.alpha_info = ttk.Label( + master=self.para_frame, text="Training epochs", font="Arial" + ) + self.alpha_info.grid( + row=2, column=0, padx=20, pady=10, sticky="nsew" + ) self.alpha = ttk.Entry( master=self.para_frame, - textvariable='alpha', + textvariable="alpha", validate="focusout", validatecommand=alpha_num_check, - width=20 + width=20, ) self.alpha.grid(row=2, column=1, padx=20, pady=10) - self.setvar('alpha', int(200)) + self.setvar("alpha", int(200)) - self.cluster_info = ttk.Label(master=self.para_frame, text="Cluster number", font="Arial") - self.cluster_info.grid(row=3, column=0, padx=20, pady=10, sticky="nsew") + self.cluster_info = ttk.Label( + master=self.para_frame, text="Cluster number", font="Arial" + ) + self.cluster_info.grid( + row=3, column=0, padx=20, pady=10, sticky="nsew" + ) self.cluster = ttk.Entry( master=self.para_frame, - textvariable='cluster', + textvariable="cluster", validate="focusout", validatecommand=cluster_num_check, - width=20 + width=20, ) self.cluster.grid(row=3, column=1, padx=20, pady=10) - self.setvar('cluster', int(7)) + self.setvar("cluster", int(7)) - self.genes_info = ttk.Label(master=self.para_frame, text="Training percentage", font="Arial") - self.genes_info.grid(row=4, column=0, padx=20, pady=10, sticky="nsew") + self.genes_info = ttk.Label( + master=self.para_frame, text="Training percentage", font="Arial" + ) + self.genes_info.grid( + row=4, column=0, padx=20, pady=10, sticky="nsew" + ) self.gene_name = ttk.Entry( master=self.para_frame, - textvariable='gene_name', + textvariable="gene_name", validate="focusout", validatecommand=gene_name_check, - width=20 + width=20, + ) + self.gene_name.grid( + row=4, column=1, padx=20, pady=10, sticky="nsew" ) - self.gene_name.grid(row=4, column=1, padx=20, pady=10, sticky="nsew") - self.setvar('gene_name', float(0.5)) + self.setvar("gene_name", float(0.5)) - self.detail_infos = ttk.Label(master=self.para_frame, text="Details", font="Arial") - self.detail_infos.grid(row=5, column=0, padx=20, pady=10, sticky="nsew") + self.detail_infos = ttk.Label( + master=self.para_frame, text="Details", font="Arial" + ) + self.detail_infos.grid( + row=5, column=0, padx=20, pady=10, sticky="nsew" + ) self.detail_info_box = ttk.Entry( master=self.para_frame, - textvariable='detail_info', + textvariable="detail_info", validate="focusout", validatecommand=detail_info_check, - width=20 + width=20, ) - self.detail_info_box.grid(row=5, column=1, padx=20, pady=10, sticky="nsew") - self.setvar('detail_info', "Deciphering spatial domains") + self.detail_info_box.grid( + row=5, column=1, padx=20, pady=10, sticky="nsew" + ) + self.setvar("detail_info", "Deciphering spatial domains") - Tooltip(self.rad_cutoff, "Image feature extraction parameters: 49(10X)") + Tooltip( + self.rad_cutoff, "Image feature extraction parameters: 49(10X)" + ) Tooltip(self.alpha, "Algorithm training epoch: 200") Tooltip(self.cluster, "Number of cluster labels: 7") Tooltip(self.gene_name, "image use rate: 0.5") @@ -850,84 +1081,107 @@ def referance_adjust(): method_btn.configure(state=DISABLED) - self.information = 'SpaGCN Deep learning' - self.functions = 'Deciphering spatial domains' - self.Run_time = '3-5 mins' + self.information = "SpaGCN Deep learning" + self.functions = "Deciphering spatial domains" + self.Run_time = "3-5 mins" self.Datatime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") style_head = ttk.Style() style_head.configure("Treeview.Heading", font="Arial") - self.tv.insert('', END, - values=(self.method_flag, - self.information, self.functions, self.Run_time, - self.Datatime)) - elif self.method_flag == 'SEDR': + self.tv.insert( + "", + END, + values=( + self.method_flag, + self.information, + self.functions, + self.Run_time, + self.Datatime, + ), + ) + elif self.method_flag == "SEDR": self.rad_cutoff_value = int(10) self.alpha_value = float(0.1) self.cluster_value = int(200) self.genes = float(0.2) self.detail_info = "Deciphering spatial domains" - self.rad_cutoff_info = ttk.Label(master=self.para_frame, text="Graph weight", font="Arial") - self.rad_cutoff_info.grid(row=1, column=0, padx=20, pady=10, sticky="nsew") + self.rad_cutoff_info = ttk.Label( + master=self.para_frame, text="Graph weight", font="Arial" + ) + self.rad_cutoff_info.grid( + row=1, column=0, padx=20, pady=10, sticky="nsew" + ) self.rad_cutoff = ttk.Entry( master=self.para_frame, - textvariable='rad_cutoff', + textvariable="rad_cutoff", validate="focusout", validatecommand=cutoff_num_check, - width=20 + width=20, ) self.rad_cutoff.grid(row=1, column=1, padx=20, pady=10) - self.setvar('rad_cutoff', int(10)) + self.setvar("rad_cutoff", int(10)) - self.alpha_info = ttk.Label(master=self.para_frame, text="Training parameter", font="Arial") - self.alpha_info.grid(row=2, column=0, padx=20, pady=10, sticky="nsew") + self.alpha_info = ttk.Label( + master=self.para_frame, text="Training parameter", font="Arial" + ) + self.alpha_info.grid( + row=2, column=0, padx=20, pady=10, sticky="nsew" + ) self.alpha = ttk.Entry( master=self.para_frame, - textvariable='alpha', + textvariable="alpha", validate="focusout", validatecommand=alpha_num_check, - width=20 + width=20, ) self.alpha.grid(row=2, column=1, padx=20, pady=10) - self.setvar('alpha', float(0.1)) + self.setvar("alpha", float(0.1)) - self.cluster_info = ttk.Label(master=self.para_frame, text="n_cluster", font="Arial") + self.cluster_info = ttk.Label( + master=self.para_frame, text="n_cluster", font="Arial" + ) self.cluster_info.grid(row=3, column=0, padx=20, pady=10) self.cluster = ttk.Entry( master=self.para_frame, - textvariable='cluster', + textvariable="cluster", validate="focusout", validatecommand=cluster_num_check, - width=20 + width=20, ) self.cluster.grid(row=3, column=1, padx=20, pady=10) - self.setvar('cluster', int(200)) + self.setvar("cluster", int(200)) - self.genes_info = ttk.Label(master=self.para_frame, text="Dropout rate", font="Arial") - self.genes_info.grid(row=4, column=0, padx=20, pady=10, sticky="nsew") + self.genes_info = ttk.Label( + master=self.para_frame, text="Dropout rate", font="Arial" + ) + self.genes_info.grid( + row=4, column=0, padx=20, pady=10, sticky="nsew" + ) self.gene_name = ttk.Entry( master=self.para_frame, - textvariable='gene_name', + textvariable="gene_name", validate="focusout", validatecommand=gene_name_check, - width=20 + width=20, ) self.gene_name.grid(row=4, column=1, padx=20, pady=10) - self.setvar('gene_name', float(0.2)) + self.setvar("gene_name", float(0.2)) - self.detail_infos = ttk.Label(master=self.para_frame, text="Details", font="Arial") + self.detail_infos = ttk.Label( + master=self.para_frame, text="Details", font="Arial" + ) self.detail_infos.grid(row=5, column=0, padx=20, pady=10) self.detail_info_box = ttk.Entry( master=self.para_frame, - textvariable='detail_info', + textvariable="detail_info", validate="focusout", validatecommand=detail_info_check, - width=20 + width=20, ) self.detail_info_box.grid(row=5, column=1, padx=20, pady=10) - self.setvar('detail_info', "Deciphering spatial domains") + self.setvar("detail_info", "Deciphering spatial domains") Tooltip(self.rad_cutoff, "parameter k in spatial graph: 10X-10") Tooltip(self.alpha, "Weight of GCN loss: 0.1") @@ -937,82 +1191,120 @@ def referance_adjust(): method_btn.configure(state=DISABLED) - self.information = 'Deep learning' - self.functions = 'Deciphering spatial domains' - self.Run_time = '3-5 mins' + self.information = "Deep learning" + self.functions = "Deciphering spatial domains" + self.Run_time = "3-5 mins" self.Datatime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") style_head = ttk.Style() style_head.configure("Treeview.Heading", font="Arial") - self.tv.insert('', END, - values=(self.method_flag, - self.information, self.functions, self.Run_time, - self.Datatime)) - elif self.method_flag == 'SCANPY': + self.tv.insert( + "", + END, + values=( + self.method_flag, + self.information, + self.functions, + self.Run_time, + self.Datatime, + ), + ) + elif self.method_flag == "SCANPY": self.rad_cutoff_value = int(20) self.cluster_value = str(3) self.detail_info = "Deciphering spatial domains" - self.rad_cutoff_info = ttk.Label(master=self.para_frame, text="PCA-dim", font="Arial") - self.rad_cutoff_info.grid(row=1, column=0, padx=20, pady=10, sticky="nsew") + self.rad_cutoff_info = ttk.Label( + master=self.para_frame, text="PCA-dim", font="Arial" + ) + self.rad_cutoff_info.grid( + row=1, column=0, padx=20, pady=10, sticky="nsew" + ) self.rad_cutoff = ttk.Entry( master=self.para_frame, - textvariable='rad_cutoff', + textvariable="rad_cutoff", validate="focusout", validatecommand=cutoff_num_check, - width=20 + width=20, ) self.rad_cutoff.grid(row=1, column=1, padx=20, pady=10) - self.setvar('rad_cutoff', int(20)) + self.setvar("rad_cutoff", int(20)) - self.cluster_info = ttk.Label(master=self.para_frame, text="Nth-cluster", font="Arial") - self.cluster_info.grid(row=2, column=0, padx=20, pady=10, sticky="nsew") + self.cluster_info = ttk.Label( + master=self.para_frame, text="Nth-cluster", font="Arial" + ) + self.cluster_info.grid( + row=2, column=0, padx=20, pady=10, sticky="nsew" + ) self.cluster = ttk.Entry( master=self.para_frame, - textvariable='cluster', + textvariable="cluster", validate="focusout", validatecommand=cluster_num_check, - width=20 + width=20, ) self.cluster.grid(row=2, column=1, padx=20, pady=10) - self.setvar('cluster', str(3)) + self.setvar("cluster", str(3)) - self.detail_infos = ttk.Label(master=self.para_frame, text="Details", font="Arial") - self.detail_infos.grid(row=3, column=0, padx=20, pady=10, sticky="nsew") + self.detail_infos = ttk.Label( + master=self.para_frame, text="Details", font="Arial" + ) + self.detail_infos.grid( + row=3, column=0, padx=20, pady=10, sticky="nsew" + ) self.detail_info_box = ttk.Entry( master=self.para_frame, - textvariable='detail_info', + textvariable="detail_info", validate="focusout", validatecommand=detail_info_check, - width=20 + width=20, ) self.detail_info_box.grid(row=3, column=1, padx=20, pady=10) - self.setvar('detail_info', "Analysis of single-cell and spatial transcriptome processes") + self.setvar( + "detail_info", + "Analysis of single-cell and spatial transcriptome processes", + ) Tooltip(self.rad_cutoff, "dimensions of pca reduction: 10X-50") - Tooltip(self.cluster, "variable gene difference detection cluster: 3") + Tooltip( + self.cluster, "variable gene difference detection cluster: 3" + ) Tooltip(self.detail_info_box, "Editable information: SCANPY") method_btn.configure(state=DISABLED) - self.information = 'Statistical data analysis' - self.functions = 'Analysis of single-cell and spatial transcriptome processes' - self.Run_time = '3-5 mins' + self.information = "Statistical data analysis" + self.functions = ( + "Analysis of single-cell and spatial transcriptome processes" + ) + self.Run_time = "3-5 mins" self.Datatime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") style_head = ttk.Style() style_head.configure("Treeview.Heading", font="Arial") - self.tv.insert('', END, - values=(self.method_flag, - self.information, self.functions, self.Run_time, - self.Datatime)) + self.tv.insert( + "", + END, + values=( + self.method_flag, + self.information, + self.functions, + self.Run_time, + self.Datatime, + ), + ) else: - Messagebox.ok(message='please input right Methods!') + Messagebox.ok(message="please input right Methods!") self.btn_states = True - self.result_setting_frame = ttk.Frame(master=self.right_panel, height=20, borderwidth=2, relief='solid') + self.result_setting_frame = ttk.Frame( + master=self.right_panel, height=20, borderwidth=2, relief="solid" + ) self.result_setting_frame.pack(after=self.info_Frame, fill=X) result_info_frame = ttk.Frame(master=self.result_setting_frame) result_info_frame.pack(side=TOP, anchor=W) - result_info_label = ttk.Label(master=result_info_frame, text=f"{self.method_flag} Cluster setting: ") + result_info_label = ttk.Label( + master=result_info_frame, + text=f"{self.method_flag} Cluster setting: ", + ) result_info_label.pack(side=TOP, anchor=W, pady=10) result_frame = ttk.Frame(master=self.result_setting_frame) @@ -1020,44 +1312,52 @@ def referance_adjust(): label = ttk.Label(result_frame, text="select file:") label.pack(side=LEFT) - entry = ttk.Entry(result_frame, textvariable='load', width=10) + entry = ttk.Entry(result_frame, textvariable="load", width=10) entry.pack(side=LEFT) - self.setvar('load', 'select trained file from computer') + self.setvar("load", "select trained file from computer") load_file_btn = ttk.Button( master=result_frame, - image='opened-folder', + image="opened-folder", bootstyle=(LINK, SECONDARY), - command=self.get_trained_file_path + command=self.get_trained_file_path, ) load_file_btn.pack(side=LEFT) - if self.method_flag == 'STAMarker': + if self.method_flag == "STAMarker": label1 = ttk.Label(result_frame, text="Single SVGs name:") label1.pack(side=LEFT) - entry1 = ttk.Entry(result_frame, textvariable='single-SVG', width=6) + entry1 = ttk.Entry(result_frame, textvariable="single-SVG", width=6) entry1.pack(side=LEFT, padx=15) - self.setvar('single-SVG', "CCDC18") + self.setvar("single-SVG", "CCDC18") label2 = ttk.Label(result_frame, text="Multi-SVGs number:") label2.pack(side=LEFT) - entry2 = ttk.Entry(result_frame, textvariable='multi-SVGs', width=6) + entry2 = ttk.Entry(result_frame, textvariable="multi-SVGs", width=6) entry2.pack(side=LEFT, padx=15) - self.setvar('multi-SVGs', 4) + self.setvar("multi-SVGs", 4) label4 = ttk.Label(result_frame, text="spot_size:") label4.pack(side=LEFT) - entry4 = ttk.Entry(result_frame, textvariable='spot_size', width=6) + entry4 = ttk.Entry(result_frame, textvariable="spot_size", width=6) entry4.pack(side=LEFT, padx=15) - self.setvar('spot_size', 100) + self.setvar("spot_size", 100) - cluster_btn = ttk.Button(result_frame, text="Confirm", command=self.Cluster_analysis_thread) + cluster_btn = ttk.Button( + result_frame, + text="Confirm", + command=self.Cluster_analysis_thread, + ) cluster_btn.pack(side=LEFT, padx=6) - button1 = ttk.Button(result_frame, text="Show", command=self.STAMarker_show) + button1 = ttk.Button( + result_frame, text="Show", command=self.STAMarker_show + ) button1.pack(side=RIGHT, padx=6) - button2 = ttk.Button(result_frame, text="Reset", command=self.remove_images) + button2 = ttk.Button( + result_frame, text="Reset", command=self.remove_images + ) button2.pack(side=RIGHT) self.spot_size = int(entry4.get()) @@ -1067,26 +1367,34 @@ def referance_adjust(): Tooltip(entry1, "Show single SVGs name: CCDC18") Tooltip(entry2, "Show Multi-SVGs, input number of genes: 4") Tooltip(entry4, "image spot size: 100") - elif self.method_flag == 'STAGE': + elif self.method_flag == "STAGE": label1 = ttk.Label(result_frame, text="Single gene name:") label1.pack(side=LEFT) - entry1 = ttk.Entry(result_frame, textvariable='gene', width=6) + entry1 = ttk.Entry(result_frame, textvariable="gene", width=6) entry1.pack(side=LEFT, padx=15) - self.setvar('gene', "Pcp4") + self.setvar("gene", "Pcp4") label4 = ttk.Label(result_frame, text="spot_size:") label4.pack(side=LEFT) - entry4 = ttk.Entry(result_frame, textvariable='Spot size', width=6) + entry4 = ttk.Entry(result_frame, textvariable="Spot size", width=6) entry4.pack(side=LEFT, padx=15) - self.setvar('Spot size', 100) + self.setvar("Spot size", 100) - cluster_btn = ttk.Button(result_frame, text="Confirm", command=self.Cluster_analysis_thread) + cluster_btn = ttk.Button( + result_frame, + text="Confirm", + command=self.Cluster_analysis_thread, + ) cluster_btn.pack(side=LEFT, padx=6) - button1 = ttk.Button(result_frame, text="Show", command=self.STAGE_show) + button1 = ttk.Button( + result_frame, text="Show", command=self.STAGE_show + ) button1.pack(side=RIGHT, padx=6) - button2 = ttk.Button(result_frame, text="Reset", command=self.remove_images) + button2 = ttk.Button( + result_frame, text="Reset", command=self.remove_images + ) button2.pack(side=RIGHT) self.spot_size = int(entry4.get()) @@ -1097,75 +1405,99 @@ def referance_adjust(): else: label1 = ttk.Label(result_frame, text="mcluster:") label1.pack(side=LEFT) - entry1 = ttk.Entry(result_frame, textvariable='mcluster', width=6) + entry1 = ttk.Entry(result_frame, textvariable="mcluster", width=6) entry1.pack(side=LEFT, padx=15) - self.setvar('mcluster', 7) + self.setvar("mcluster", 7) label2 = ttk.Label(result_frame, text="louvain:") label2.pack(side=LEFT) - entry2 = ttk.Entry(result_frame, textvariable='louvain', width=6) + entry2 = ttk.Entry(result_frame, textvariable="louvain", width=6) entry2.pack(side=LEFT, padx=15) - self.setvar('louvain', 0.65) + self.setvar("louvain", 0.65) - if self.method_flag == 'STAGATE': + if self.method_flag == "STAGATE": label3 = ttk.Label(result_frame, text="kmeans:") label3.pack(side=LEFT) - entry3 = ttk.Entry(result_frame, textvariable='kmeans', width=6) + entry3 = ttk.Entry(result_frame, textvariable="kmeans", width=6) entry3.pack(side=LEFT, padx=15) - self.setvar('kmeans', 7) + self.setvar("kmeans", 7) self.kmeans_num = int(entry3.get()) Tooltip(entry3, "Kmean cluster number: 7") label4 = ttk.Label(result_frame, text="spot_size:") label4.pack(side=LEFT) - entry4 = ttk.Entry(result_frame, textvariable='spot_size', width=6) + entry4 = ttk.Entry( + result_frame, textvariable="spot_size", width=6 + ) entry4.pack(side=LEFT, padx=15) - self.setvar('spot_size', 100) + self.setvar("spot_size", 100) - cluster_btn = ttk.Button(result_frame, text="Confirm", command=self.Cluster_analysis_thread) + cluster_btn = ttk.Button( + result_frame, + text="Confirm", + command=self.Cluster_analysis_thread, + ) cluster_btn.pack(side=LEFT, padx=6) - button1 = ttk.Button(result_frame, text="Show", command=self.STAGATE_show) + button1 = ttk.Button( + result_frame, text="Show", command=self.STAGATE_show + ) button1.pack(side=RIGHT, padx=6) - if self.method_flag == 'SEDR': + if self.method_flag == "SEDR": label3 = ttk.Label(result_frame, text="kmeans:") label3.pack(side=LEFT) - entry3 = ttk.Entry(result_frame, textvariable='kmeans', width=6) + entry3 = ttk.Entry(result_frame, textvariable="kmeans", width=6) entry3.pack(side=LEFT, padx=15) - self.setvar('kmeans', 7) + self.setvar("kmeans", 7) self.kmeans_num = int(entry3.get()) Tooltip(entry3, "Kmean cluster number: 7") label4 = ttk.Label(result_frame, text="spot_size:") label4.pack(side=LEFT) - entry4 = ttk.Entry(result_frame, textvariable='spot_size', width=6) + entry4 = ttk.Entry( + result_frame, textvariable="spot_size", width=6 + ) entry4.pack(side=LEFT, padx=15) - self.setvar('spot_size', 100) + self.setvar("spot_size", 100) - cluster_btn = ttk.Button(result_frame, text="Confirm", command=self.Cluster_analysis_thread) + cluster_btn = ttk.Button( + result_frame, + text="Confirm", + command=self.Cluster_analysis_thread, + ) cluster_btn.pack(side=LEFT, padx=6) - button1 = ttk.Button(result_frame, text="Show", command=self.SEDR_show) + button1 = ttk.Button( + result_frame, text="Show", command=self.SEDR_show + ) button1.pack(side=RIGHT, padx=6) - if self.method_flag == 'SCANPY': + if self.method_flag == "SCANPY": label3 = ttk.Label(result_frame, text="kmeans:") label3.pack(side=LEFT) - entry3 = ttk.Entry(result_frame, textvariable='kmeans', width=6) + entry3 = ttk.Entry(result_frame, textvariable="kmeans", width=6) entry3.pack(side=LEFT, padx=15) - self.setvar('kmeans', 7) + self.setvar("kmeans", 7) self.kmeans_num = int(entry3.get()) Tooltip(entry3, "Kmean cluster number: 7") label4 = ttk.Label(result_frame, text="spot_size:") label4.pack(side=LEFT) - entry4 = ttk.Entry(result_frame, textvariable='spot_size', width=6) + entry4 = ttk.Entry( + result_frame, textvariable="spot_size", width=6 + ) entry4.pack(side=LEFT, padx=15) - self.setvar('spot_size', 100) + self.setvar("spot_size", 100) - cluster_btn = ttk.Button(result_frame, text="Confirm", command=self.Cluster_analysis_thread) + cluster_btn = ttk.Button( + result_frame, + text="Confirm", + command=self.Cluster_analysis_thread, + ) cluster_btn.pack(side=LEFT, padx=6) - button1 = ttk.Button(result_frame, text="Show", command=self.SCANPY_show) + button1 = ttk.Button( + result_frame, text="Show", command=self.SCANPY_show + ) button1.pack(side=RIGHT, padx=6) # label4 = ttk.Label(result_frame, text="spot_size:") @@ -1174,31 +1506,49 @@ def referance_adjust(): # entry4.pack(side=LEFT, padx=15) # self.setvar('spot_size', 100) - if self.method_flag == 'STAligner': + if self.method_flag == "STAligner": label4 = ttk.Label(result_frame, text="spot_size:") label4.pack(side=LEFT) - entry4 = ttk.Entry(result_frame, textvariable='spot_size', width=6) + entry4 = ttk.Entry( + result_frame, textvariable="spot_size", width=6 + ) entry4.pack(side=LEFT, padx=15) - self.setvar('spot_size', 100) + self.setvar("spot_size", 100) - cluster_btn = ttk.Button(result_frame, text="Confirm", command=self.Cluster_analysis_thread) + cluster_btn = ttk.Button( + result_frame, + text="Confirm", + command=self.Cluster_analysis_thread, + ) cluster_btn.pack(side=LEFT, padx=6) - button1 = ttk.Button(result_frame, text="Show", command=self.STAligner_show) + button1 = ttk.Button( + result_frame, text="Show", command=self.STAligner_show + ) button1.pack(side=RIGHT, padx=6) - if self.method_flag == 'SpaGCN': + if self.method_flag == "SpaGCN": label4 = ttk.Label(result_frame, text="spot_size:") label4.pack(side=LEFT) - entry4 = ttk.Entry(result_frame, textvariable='spot_size', width=6) + entry4 = ttk.Entry( + result_frame, textvariable="spot_size", width=6 + ) entry4.pack(side=LEFT, padx=15) - self.setvar('spot_size', 100) + self.setvar("spot_size", 100) - cluster_btn = ttk.Button(result_frame, text="Confirm", command=self.Cluster_analysis_thread) + cluster_btn = ttk.Button( + result_frame, + text="Confirm", + command=self.Cluster_analysis_thread, + ) cluster_btn.pack(side=LEFT, padx=6) - button1 = ttk.Button(result_frame, text="Show", command=self.SpaGCN_show) + button1 = ttk.Button( + result_frame, text="Show", command=self.SpaGCN_show + ) button1.pack(side=RIGHT, padx=6) - button2 = ttk.Button(result_frame, text="Reset", command=self.remove_images) + button2 = ttk.Button( + result_frame, text="Reset", command=self.remove_images + ) button2.pack(side=RIGHT) self.louvain_res = float(entry2.get()) @@ -1210,15 +1560,17 @@ def referance_adjust(): Tooltip(entry4, "image spot size: 100") except: self.btn_states = True - Messagebox.show_warning(title="Attention", message='Make sure your data had beed loaded!') + Messagebox.show_warning( + title="Attention", message="Make sure your data had beed loaded!" + ) self.btn_states = True method_btn = ttk.Button( master=self.frames, - text='Confirm', + text="Confirm", width=6, - style='my.TButton', - command=referance_adjust + style="my.TButton", + command=referance_adjust, ) method_btn.pack(side=LEFT) self.method_flag = methods[0] @@ -1231,71 +1583,61 @@ def submit_result(event): self.result_setting_frame.destroy() method_btn.configure(state=ACTIVE) self.method_flag = self.select_box_obj.get() - print('Current choose: {}'.format(self.select_box_obj.get())) + print("Current choose: {}".format(self.select_box_obj.get())) - self.select_box_obj.bind('<>', submit_result) + self.select_box_obj.bind("<>", submit_result) status_cf = CollapsingFrame(self.left_panel) status_cf.pack(fill=BOTH, pady=1) status_frm = ttk.Frame(status_cf, padding=10) status_frm.columnconfigure(1, weight=1) - status_cf.add( - child=status_frm, - title='Running Status', - bootstyle=SECONDARY - ) + status_cf.add(child=status_frm, title="Running Status", bootstyle=SECONDARY) - lbl = ttk.Label( - master=status_frm, - textvariable='prog-message' - ) + lbl = ttk.Label(master=status_frm, textvariable="prog-message") lbl.configure(font="Arial") lbl.grid(row=0, column=0, columnspan=2, sticky=W) - self.setvar('prog-message', 'choosing methods...') + self.setvar("prog-message", "choosing methods...") self.pb = ttk.Progressbar( - master=status_frm, - mode='determinate', - length=100, - orient=HORIZONTAL + master=status_frm, mode="determinate", length=100, orient=HORIZONTAL ) self.pb.grid(row=1, column=0, columnspan=2, sticky=EW, pady=(10, 5)) - lbl = ttk.Label(status_frm, text='Start time:') + lbl = ttk.Label(status_frm, text="Start time:") lbl.configure(font="Arial") lbl.grid(row=2, column=0, sticky=W, pady=2) - lbl = ttk.Label(status_frm, textvariable='prog-time-started') + lbl = ttk.Label(status_frm, textvariable="prog-time-started") lbl.grid(row=2, column=1, columnspan=2, sticky=EW, padx=2, pady=5) - self.setvar('prog-time-started', None) - lbl = ttk.Label(status_frm, text='End time:') + self.setvar("prog-time-started", None) + lbl = ttk.Label(status_frm, text="End time:") lbl.configure(font="Arial") lbl.grid(row=3, column=0, sticky=W, pady=2) - lbl = ttk.Label(status_frm, textvariable='End-time') + lbl = ttk.Label(status_frm, textvariable="End-time") lbl.grid(row=3, column=1, columnspan=2, sticky=EW, pady=5, padx=2) - self.setvar('End-time', None) + self.setvar("End-time", None) - lbl = ttk.Label(status_frm, text='Cost time:') + lbl = ttk.Label(status_frm, text="Cost time:") lbl.configure(font="Arial") lbl.grid(row=4, column=0, sticky=W, pady=2) - lbl = ttk.Label(status_frm, textvariable='total-time-cost') + lbl = ttk.Label(status_frm, textvariable="total-time-cost") lbl.grid(row=4, column=1, columnspan=2, sticky=EW, pady=5, padx=2) - self.setvar('total-time-cost', None) + self.setvar("total-time-cost", None) sep = ttk.Separator(status_frm, bootstyle=SECONDARY) sep.grid(row=5, column=0, columnspan=2, pady=10, sticky=EW) - lbl = ttk.Label(status_frm, text='Now used method:') + lbl = ttk.Label(status_frm, text="Now used method:") lbl.configure(font="Arial") lbl.grid(row=6, column=0, sticky=W, pady=5) - lbl = ttk.Label(status_frm, textvariable='current-file-msg') + lbl = ttk.Label(status_frm, textvariable="current-file-msg") lbl.configure(font="Arial") lbl.grid(row=6, column=1, columnspan=2, pady=5, sticky=EW, padx=5) - self.setvar('current-file-msg', None) + self.setvar("current-file-msg", None) - lbl = ttk.Label(self.left_panel, image='logo', style='bg.TLabel') - lbl.pack(side='bottom') + lbl = ttk.Label(self.left_panel, image="logo", style="bg.TLabel") + lbl.pack(side="bottom") self.right_panel = ttk.Frame(self, padding=(2, 1)) self.right_panel.pack(side=RIGHT, fill=BOTH, expand=YES) @@ -1306,28 +1648,40 @@ def submit_result(event): self.ybar = ttk.Scrollbar(self.info_Frame) self.ybar.pack(side=RIGHT, fill=Y) - self.tv = ttk.Treeview(self.info_Frame, show='headings', height=5, yscrollcommand=self.ybar.set) - self.tv.configure(columns=( - 'Method', 'information', 'functions', - 'Estimated time cost', 'datetime' - )) + self.tv = ttk.Treeview( + self.info_Frame, show="headings", height=5, yscrollcommand=self.ybar.set + ) + self.tv.configure( + columns=( + "Method", + "information", + "functions", + "Estimated time cost", + "datetime", + ) + ) style = ttk.Style() def fixed_map(option): - return [elm for elm in style.map('Treeview', query_opt=option) if elm[:2] != ('!disabled', '!selected')] - - style.map('Treeview', - foreground=fixed_map('foreground'), - background=fixed_map('background'), - ) - style.configure('Treeview.Heading', font='Arial') - style.configure('Treeview', font='Arial') - self.tv.column('Method', width=150, stretch=True) + return [ + elm + for elm in style.map("Treeview", query_opt=option) + if elm[:2] != ("!disabled", "!selected") + ] + + style.map( + "Treeview", + foreground=fixed_map("foreground"), + background=fixed_map("background"), + ) + style.configure("Treeview.Heading", font="Arial") + style.configure("Treeview", font="Arial") + self.tv.column("Method", width=150, stretch=True) - for col in ['information', 'Estimated time cost', 'datetime']: + for col in ["information", "Estimated time cost", "datetime"]: self.tv.column(col, stretch=False) - for col in self.tv['columns']: + for col in self.tv["columns"]: self.tv.heading(col, text=col.title(), anchor=W) self.ybar.config(command=self.tv.yview) @@ -1337,56 +1691,65 @@ def fixed_map(option): self.scroll_cf.pack(fill=BOTH, expand=YES) self.output_container = ttk.Frame(self.scroll_cf, padding=1) - self.scroll_cf.add(self.output_container, textvariable='scroll-message') - - self._value = 'Log: ' + 'STABox' + ' is ready, the visualization results are displayed below......' - self.setvar('scroll-message', self._value) + self.scroll_cf.add(self.output_container, textvariable="scroll-message") - path = '../Renv_setting.yaml' - if os.path.exists(path): - with open(path, 'r') as f: - yamlData = yaml.safe_load(f) - os.environ['R_HOME'] = yamlData['R_HOME'] - os.environ['R_USER'] = yamlData['R_USER'] - else: - Messagebox.show_error(title='Warning', message='please setting R environ first!') + self._value = ( + "Log: " + + "STABox" + + " is ready, the visualization results are displayed below......" + ) + self.setvar("scroll-message", self._value) def Cluster_analysis(self): - if self.method_flag == 'STAGATE': + if self.method_flag == "STAGATE": if self.trained_file_path is not None: adata = sc.read(self.trained_file_path) - sc.pp.neighbors(adata, use_rep='STAGATE') + sc.pp.neighbors(adata, use_rep="STAGATE") sc.tl.umap(adata) - adata = mclust_R(adata, used_obsm='STAGATE', num_cluster=self.Mcluster_num) - sc.pp.pca(adata, n_comps=50, use_highly_variable=True, svd_solver='arpack') - sc.pp.neighbors(adata, use_rep='X_pca') + adata = mclust_R( + adata, used_obsm="STAGATE", num_cluster=self.Mcluster_num + ) + sc.pp.pca( + adata, n_comps=50, use_highly_variable=True, svd_solver="arpack" + ) + sc.pp.neighbors(adata, use_rep="X_pca") sc.tl.louvain(adata, resolution=self.louvain_res) kmeans = KMeans(n_clusters=self.Mcluster_num) kmeans.fit(adata.X) - adata.obs['STAGATE_kmeans'] = kmeans.labels_ - adata.obs['STAGATE_kmeans'] = adata.obs['STAGATE_kmeans'].astype('category') + adata.obs["STAGATE_kmeans"] = kmeans.labels_ + adata.obs["STAGATE_kmeans"] = adata.obs["STAGATE_kmeans"].astype( + "category" + ) self.result_queue.put(adata) del adata - elif self.method_flag == 'STAligner': + elif self.method_flag == "STAligner": if self.trained_file_path is not None: adata_new = sc.read(self.trained_file_path) - sc.tl.louvain(adata_new, random_state=666, key_added="louvain", - resolution=float(self.louvain_res)) - mclust_R(adata_new, num_cluster=int(self.Mcluster_num), used_obsm='STAligner') + sc.tl.louvain( + adata_new, + random_state=666, + key_added="louvain", + resolution=float(self.louvain_res), + ) + mclust_R( + adata_new, num_cluster=int(self.Mcluster_num), used_obsm="STAligner" + ) if self.label_files_exit: # adata_list = sc.read(os.path.join(running_path, "result", "STAligner_GroundTruth_output.h5ad")) adata_list = {} key_add = [] print(self.multi_files) for section_id in self.multi_files: - file_name = section_id.rsplit('\\', 1)[-1] - k = file_name.rsplit('.', 1)[-2] + file_name = section_id.rsplit("\\", 1)[-1] + k = file_name.rsplit(".", 1)[-2] key_add.append(k) temp_adata = sc.read(section_id) temp_adata.var_names_make_unique() - temp_adata.obs_names = [x + '_' + k for x in temp_adata.obs_names] + temp_adata.obs_names = [ + x + "_" + k for x in temp_adata.obs_names + ] adata_list[k] = temp_adata.copy() # self.result_queue.put(adata_list) # adata_list.write_h5ad(os.path.join(running_path, "result", "STAligner_GroundTruth_output.h5ad")) @@ -1396,54 +1759,72 @@ def Cluster_analysis(self): self.result_queue.put(adata_new) del adata_new - elif self.method_flag == 'STAMarker': + elif self.method_flag == "STAMarker": if self.trained_file_path is not None: ann_data = sc.read(self.trained_file_path) self.result_queue.put(ann_data) del ann_data - elif self.method_flag == 'STAGE': + elif self.method_flag == "STAGE": if self.trained_file_path is not None: - adata = sc.read(os.path.join(running_path, "result", "STAGE_raw_output.h5ad")) - adata_sample = sc.read(os.path.join(running_path, "result", "STAGE_adata_sample_output.h5ad")) - adata_stage = sc.read(os.path.join(running_path, "result", "STAGE_adata_stage_output.h5ad")) + adata = sc.read( + os.path.join(running_path, "result", "STAGE_raw_output.h5ad") + ) + adata_sample = sc.read( + os.path.join( + running_path, "result", "STAGE_adata_sample_output.h5ad" + ) + ) + adata_stage = sc.read( + os.path.join( + running_path, "result", "STAGE_adata_stage_output.h5ad" + ) + ) self.result_queue.put(adata) self.result_queue.put(adata_sample) self.result_queue.put(adata_stage) del adata, adata_sample, adata_stage - elif self.method_flag == 'SpaGCN': + elif self.method_flag == "SpaGCN": if self.trained_file_path is not None: adata = sc.read(self.trained_file_path) sc.tl.louvain(adata, resolution=self.louvain_res) self.result_queue.put(adata) del adata - elif self.method_flag == 'SEDR': + elif self.method_flag == "SEDR": if self.trained_file_path is not None: try: adata = sc.read(self.trained_file_path) eval_cluster = int(self.Mcluster_num) eval_resolution = res_search_fixed_clus(adata, eval_cluster) - sc.tl.leiden(adata, key_added="SEDR_leiden", resolution=eval_resolution) + sc.tl.leiden( + adata, key_added="SEDR_leiden", resolution=eval_resolution + ) kmeans = KMeans(n_clusters=self.kmeans_num) kmeans.fit(adata.X) - adata.obs['SEDR_kmeans'] = kmeans.labels_ - adata.obs['SEDR_kmeans'] = adata.obs['SEDR_kmeans'].astype('int') - adata.obs['SEDR_kmeans'] = adata.obs['SEDR_kmeans'].astype('category') + adata.obs["SEDR_kmeans"] = kmeans.labels_ + adata.obs["SEDR_kmeans"] = adata.obs["SEDR_kmeans"].astype("int") + adata.obs["SEDR_kmeans"] = adata.obs["SEDR_kmeans"].astype( + "category" + ) import rpy2.robjects as robjects + robjects.r.library("mclust") import rpy2.robjects.numpy2ri + rpy2.robjects.numpy2ri.activate() - rmclust = robjects.r['Mclust'] - res2 = rmclust(adata.X, eval_cluster, 'EEE') + rmclust = robjects.r["Mclust"] + res2 = rmclust(adata.X, eval_cluster, "EEE") mclust_res = np.array(res2[-2]) - adata.obs['SEDR_mclust'] = mclust_res + adata.obs["SEDR_mclust"] = mclust_res # adata.obs['SEDR_mclust'] = mclust_R(adata_sedr.X, eval_cluster) - adata.obs['SEDR_mclust'] = adata.obs['SEDR_mclust'].astype('int') - adata.obs['SEDR_mclust'] = adata.obs['SEDR_mclust'].astype('category') + adata.obs["SEDR_mclust"] = adata.obs["SEDR_mclust"].astype("int") + adata.obs["SEDR_mclust"] = adata.obs["SEDR_mclust"].astype( + "category" + ) self.result_queue.put(adata) del adata @@ -1453,19 +1834,23 @@ def Cluster_analysis(self): if self.trained_file_path is not None: adata = sc.read(self.trained_file_path) if self.label_files_exit: - adata = adata[adata.obs['GroundTruth'] == adata.obs['GroundTruth'],] + adata = adata[adata.obs["GroundTruth"] == adata.obs["GroundTruth"],] else: adata.obsm["spatial"] = adata.obsm["spatial"] * (-1) eval_cluster = int(self.Mcluster_num) eval_resolution = res_search_fixed_clus(adata, eval_cluster) - sc.tl.leiden(adata, key_added="SCANPY_leiden", resolution=eval_resolution) + sc.tl.leiden( + adata, key_added="SCANPY_leiden", resolution=eval_resolution + ) kmeans = KMeans(n_clusters=self.kmeans_num) kmeans.fit(adata.X) - adata.obs['SCANPY_kmeans'] = kmeans.labels_ - adata.obs['SCANPY_kmeans'] = adata.obs['SCANPY_kmeans'].astype('int') - adata.obs['SCANPY_kmeans'] = adata.obs['SCANPY_kmeans'].astype('category') + adata.obs["SCANPY_kmeans"] = kmeans.labels_ + adata.obs["SCANPY_kmeans"] = adata.obs["SCANPY_kmeans"].astype("int") + adata.obs["SCANPY_kmeans"] = adata.obs["SCANPY_kmeans"].astype( + "category" + ) sc.tl.rank_genes_groups(adata, "leiden", inplace=True) self.result_queue.put(adata) del adata @@ -1473,35 +1858,75 @@ def Cluster_analysis(self): if self.file_path is None: self.file_path = self.trained_file_path self.pb.stop() - self.pb['value'] = 100 - self.setvar('prog-message', 'Cluster analysis run over!') + self.pb["value"] = 100 + self.setvar("prog-message", "Cluster analysis run over!") + self.setvar("End-time", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + EndTime = datetime.now().replace(microsecond=0) + self.setvar("total-time-cost", EndTime - self.StartTime) + + def run_cluster_analysis(self): + try: + self.Cluster_analysis() + finally: + self.is_running = False + + def task_done(self, future): + # 处理任务完成后的清理工作 + exception = future.exception() + if exception: + messagebox.showerror("Error", f"Cluster analysis failed: {exception}") def Cluster_analysis_thread(self): - print(self.model_train_flag) - # temp - # self.model_train_flag = True + # 弹出确认对话框 + confirm = messagebox.askyesno( + title="GroundTruth Check", + message="Ensure the file contains the GroundTruth information, do you want to continue?", + ) + if confirm: + self.label_files_exit = True + + if not hasattr(self, "executor"): + # 初始化线程池,最大线程数设为1,确保同一时间只有一个线程执行任务 + self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=1) + + if not hasattr(self, "is_running"): + self.is_running = False + + if self.is_running: + messagebox.showinfo("Warning", "Cluster analysis is already running.") + return + print("model_train_flag: ", self.model_train_flag) if self.model_train_flag: # self.result_flag = True self.pb.start() - self.setvar('prog-message', f'{self.method_flag}: cluster analysis underway!!') - T = threading.Thread(target=self.Cluster_analysis) - T.start() + self.setvar("End-time", "") + self.setvar("total-time-cost", "") + self.setvar( + "prog-message", f"{self.method_flag}: cluster analysis underway!!" + ) + self.setvar("prog-time-started", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + self.StartTime = datetime.now().replace(microsecond=0) + self.is_running = True + future = self.executor.submit(self.run_cluster_analysis) + future.add_done_callback(self.task_done) def data_download_GUI(self): self.path_load_flag = False datadown_gui = ttk.Toplevel(self.downloadbtn) datadown_gui.title("Data download") - datadown_gui.geometry('1050x350') + datadown_gui.geometry("1050x350") style = Style() style.configure("TCheckbutton", font=("Arial", 10)) - style.configure('TButton', font=('Arial', 10)) - style.configure('TLabel', font=('Arial', 10)) - style.configure('TRadiobutton', font=('Arial', 10)) - style.configure('TCombobox', font=('Arial', 10)) + style.configure("TButton", font=("Arial", 10)) + style.configure("TLabel", font=("Arial", 10)) + style.configure("TRadiobutton", font=("Arial", 10)) + style.configure("TCombobox", font=("Arial", 10)) database_select_info_frame = ttk.Frame(datadown_gui) - database_select_info_frame.pack(side=TOP, anchor='nw') + database_select_info_frame.pack(side=TOP, anchor="nw") - database_select_info = ttk.Label(database_select_info_frame, text='Select ST Database: ') + database_select_info = ttk.Label( + database_select_info_frame, text="Select ST Database: " + ) database_select_info.pack(side=LEFT) database_select_frame = ttk.Frame(datadown_gui) @@ -1519,88 +1944,134 @@ def on_radio_select(value): data_download_frame = ttk.Frame(self.data_download_frame) data_download_frame.pack(side=TOP) comfirm_btn_frame = ttk.Frame(self.data_download_frame) - comfirm_btn_frame.pack(anchor='center') - catagory = ["Spatial Transcriptomics", "Spatial Proteomics", "Spatial Metabolomics", "Spatial Genomics", - "Spatial MultiOmics"] - catagory_label = ttk.Label(data_download_frame, text='Data catagory:') + comfirm_btn_frame.pack(anchor="center") + catagory = [ + "Spatial Transcriptomics", + "Spatial Proteomics", + "Spatial Metabolomics", + "Spatial Genomics", + "Spatial MultiOmics", + ] + catagory_label = ttk.Label(data_download_frame, text="Data catagory:") catagory_label.grid(row=0, column=0) + def set_data_type_download(event): - print('Current choose: {}'.format(catagory_combobox.get())) - list_experiment_label = ttk.Label(data_download_frame, text='Data experiment:') + print("Current choose: {}".format(catagory_combobox.get())) + list_experiment_label = ttk.Label( + data_download_frame, text="Data experiment:" + ) list_experiment_label.grid(row=0, column=2) def set_data_experiment_download(event): - print('Current choose: {}'.format(list_experiment_combobox.get())) - list_data_label = ttk.Label(data_download_frame, text='Data type:') + print( + "Current choose: {}".format(list_experiment_combobox.get()) + ) + list_data_label = ttk.Label( + data_download_frame, text="Data type:" + ) list_data_label.grid(row=0, column=4) + def data_type_download(event): - print('Current choose: {}'.format(list_data_combobox.get())) + print("Current choose: {}".format(list_data_combobox.get())) if list_data_combobox.get() is not None: + def download_data(): # adata = sodb.load_experiment(list_experiment_combobox.get(),list_data_combobox.get()) scrollbar = ttk.Scrollbar(comfirm_btn_frame) scrollbar.pack(side=RIGHT, fill=Y) - text_box = ttk.Text(comfirm_btn_frame, yscrollcommand=scrollbar.set) + text_box = ttk.Text( + comfirm_btn_frame, yscrollcommand=scrollbar.set + ) text_box.pack(after=btn, fill=BOTH, expand=True) # scrollbar = tk.Scrollbar(root) # scrollbar.pack(side=RIGHT, fill=Y) scrollbar.config(command=text_box.yview) text_box.insert(tk.END, f"Current database: SODB\n") - text_box.insert(tk.END, f"Current data catagory: {catagory_combobox.get()}\n") - text_box.insert(tk.END, f"Current technology: {list_experiment_combobox.get()}\n") - text_box.insert(tk.END, f"Current data type: {list_data_combobox.get()}\n") - text_box.insert(tk.END, f"Current data saved path: {os.path.join(running_path, 'dataset', 'cache')}\n") + text_box.insert( + tk.END, + f"Current data catagory: {catagory_combobox.get()}\n", + ) + text_box.insert( + tk.END, + f"Current technology: {list_experiment_combobox.get()}\n", + ) + text_box.insert( + tk.END, + f"Current data type: {list_data_combobox.get()}\n", + ) + text_box.insert( + tk.END, + f"Current data saved path: {os.path.join(running_path, 'dataset', 'cache')}\n", + ) self.pb.start() - self.setvar('prog-message', 'Data start download!!') - self.data_download_thread(sodb, "SODB", list_experiment_combobox.get(),list_data_combobox.get()) - btn = ttk.Button(master=comfirm_btn_frame, text='Confirm', command=download_data) + self.setvar("prog-message", "Data start download!!") + self.data_download_thread( + sodb, + "SODB", + list_experiment_combobox.get(), + list_data_combobox.get(), + ) + + btn = ttk.Button( + master=comfirm_btn_frame, + text="Confirm", + command=download_data, + ) btn.pack(side=TOP) if list_experiment_combobox.get() is not None: - datas = sodb.list_experiment_by_dataset(list_experiment_combobox.get()) + datas = sodb.list_experiment_by_dataset( + list_experiment_combobox.get() + ) list_data_combobox = ttk.Combobox( master=data_download_frame, - textvariable='select_list_data', - font=('Arial', 10), + textvariable="select_list_data", + font=("Arial", 10), values=datas, - state='normal', - cursor='plus', + state="normal", + cursor="plus", ) list_data_combobox.current(0) list_data_combobox.grid(row=0, column=5) - list_data_combobox.bind('<>', data_type_download) + list_data_combobox.bind( + "<>", data_type_download + ) if catagory_combobox.get() is not None: - data_list = sodb.list_dataset_by_category(catagory_combobox.get()) + data_list = sodb.list_dataset_by_category( + catagory_combobox.get() + ) list_experiment_combobox = ttk.Combobox( - master=data_download_frame, - textvariable='select_list_experiment', - font=('Arial', 10), - values=data_list, - state='normal', - cursor='plus', - ) + master=data_download_frame, + textvariable="select_list_experiment", + font=("Arial", 10), + values=data_list, + state="normal", + cursor="plus", + ) list_experiment_combobox.current(0) list_experiment_combobox.grid(row=0, column=3) - list_experiment_combobox.bind('<>', set_data_experiment_download) + list_experiment_combobox.bind( + "<>", set_data_experiment_download + ) catagory_combobox = ttk.Combobox( master=data_download_frame, - textvariable='select_data_catagory', - font=('Arial', 10), + textvariable="select_data_catagory", + font=("Arial", 10), values=catagory, - state='normal', - cursor='plus', + state="normal", + cursor="plus", ) catagory_combobox.current(0) catagory_combobox.grid(row=0, column=1) - catagory_combobox.bind('<>', set_data_type_download) + catagory_combobox.bind("<>", set_data_type_download) self.path_load_flag = True else: self.data_download_frame = ttk.Frame(datadown_gui) @@ -1608,78 +2079,123 @@ def download_data(): data_download_frame = ttk.Frame(self.data_download_frame) data_download_frame.pack(side=TOP) comfirm_btn_frame = ttk.Frame(self.data_download_frame) - comfirm_btn_frame.pack(anchor='center') - catagory_label = ttk.Label(data_download_frame, text='Data catagory:') + comfirm_btn_frame.pack(anchor="center") + catagory_label = ttk.Label(data_download_frame, text="Data catagory:") catagory_label.grid(row=0, column=0) def set_data_type_download(event): - print('Current choose: {}'.format(catagory_combobox.get())) - list_experiment_label = ttk.Label(data_download_frame, text='Data experiment:') + print("Current choose: {}".format(catagory_combobox.get())) + list_experiment_label = ttk.Label( + data_download_frame, text="Data experiment:" + ) list_experiment_label.grid(row=0, column=2) def set_data_experiment_download(event): if list_experiment_combobox.get() is not None: - print('Current choose: {}'.format(list_experiment_combobox.get())) + print( + "Current choose: {}".format( + list_experiment_combobox.get() + ) + ) if list_experiment_combobox.get() is not None: + def download_data(): # spatialdb.download(list_experiment_combobox.get()) scrollbar = ttk.Scrollbar(comfirm_btn_frame) scrollbar.pack(side=RIGHT, fill=Y) - text_box = ttk.Text(comfirm_btn_frame, yscrollcommand=scrollbar.set) - text_box.pack(after=btn, side=TOP, fill=BOTH, expand=True) + text_box = ttk.Text( + comfirm_btn_frame, yscrollcommand=scrollbar.set + ) + text_box.pack( + after=btn, side=TOP, fill=BOTH, expand=True + ) scrollbar.config(command=text_box.yview) - text_box.insert(tk.END, f"Current database: SpatialDB\n") - text_box.insert(tk.END, f"Current data catagory: {catagory_combobox.get()}\n") - text_box.insert(tk.END, f"Current data type: {list_experiment_combobox.get()}\n") + text_box.insert( + tk.END, f"Current database: SpatialDB\n" + ) + text_box.insert( + tk.END, + f"Current data catagory: {catagory_combobox.get()}\n", + ) + text_box.insert( + tk.END, + f"Current data type: {list_experiment_combobox.get()}\n", + ) # text_box.insert(tk.END, f"Current data type: {list_data_combobox.get()}\n") - text_box.insert(tk.END, f"Current data saved path: {os.path.join(running_path, 'dataset', 'cache')}\n") + text_box.insert( + tk.END, + f"Current data saved path: {os.path.join(running_path, 'dataset', 'cache')}\n", + ) self.pb.start() - self.setvar('prog-message', 'Data start download!!') - self.data_download_thread(spatialdb, "SpatialDB", None, list_experiment_combobox.get()) - - btn = ttk.Button(master=comfirm_btn_frame, text='Confirm', command=download_data) + self.setvar("prog-message", "Data start download!!") + self.data_download_thread( + spatialdb, + "SpatialDB", + None, + list_experiment_combobox.get(), + ) + + btn = ttk.Button( + master=comfirm_btn_frame, + text="Confirm", + command=download_data, + ) btn.pack(side=TOP) if catagory_combobox.get() is not None: - data_list = spatialdb.get_download_data_info(catagory_combobox.get()) - data_list = [i.split('.', 1)[0] for i in data_list] + data_list = spatialdb.get_download_data_info( + catagory_combobox.get() + ) + data_list = [i.split(".", 1)[0] for i in data_list] list_experiment_combobox = ttk.Combobox( master=data_download_frame, - textvariable='select_list_experiment', - font=('Arial', 10), + textvariable="select_list_experiment", + font=("Arial", 10), values=data_list, - state='normal', - cursor='plus', + state="normal", + cursor="plus", ) list_experiment_combobox.current(0) list_experiment_combobox.grid(row=0, column=3) - list_experiment_combobox.bind('<>', set_data_experiment_download) + list_experiment_combobox.bind( + "<>", set_data_experiment_download + ) catagory_combobox = ttk.Combobox( master=data_download_frame, - textvariable='select_data_catagory', - font=('Arial', 10), + textvariable="select_data_catagory", + font=("Arial", 10), values=spatialdb.get_download_data_type(), - state='normal', - cursor='plus', + state="normal", + cursor="plus", ) catagory_combobox.current(0) catagory_combobox.grid(row=0, column=1) - catagory_combobox.bind('<>', set_data_type_download) + catagory_combobox.bind("<>", set_data_type_download) self.path_load_flag = True radio_var = tk.StringVar() - radio1 = ttk.Radiobutton(database_select_frame, text="Download ST data from SODB", style="TCheckbutton", - variable=radio_var, value="SODB", - command=lambda: on_radio_select("SODB")) + radio1 = ttk.Radiobutton( + database_select_frame, + text="Download ST data from SODB", + style="TCheckbutton", + variable=radio_var, + value="SODB", + command=lambda: on_radio_select("SODB"), + ) radio1.grid(row=0, column=0, padx=5, pady=5, sticky="w") - radio2 = ttk.Radiobutton(database_select_frame, text="Download ST data from SpatialDB", style="TCheckbutton", - variable=radio_var, value="SpatialDB", - command=lambda: on_radio_select("SpatialDB")) + radio2 = ttk.Radiobutton( + database_select_frame, + text="Download ST data from SpatialDB", + style="TCheckbutton", + variable=radio_var, + value="SpatialDB", + command=lambda: on_radio_select("SpatialDB"), + ) radio2.grid(row=1, column=0, padx=5, pady=5, sticky="w") def on_closing(): @@ -1691,19 +2207,22 @@ def on_closing(): def data_download(self, db_class, db_flag, experiment_type, data_type): if db_flag == "SODB": db_class.load_experiment(experiment_type, data_type) - self.setvar('prog-message', f'Data download complete!!') + self.setvar("prog-message", f"Data download complete!!") self.pb.stop() - self.pb['value'] = 100 + self.pb["value"] = 100 else: db_class.download(data_type) - self.setvar('prog-message', f'Data download complete!!') + self.setvar("prog-message", f"Data download complete!!") self.pb.stop() - self.pb['value'] = 100 + self.pb["value"] = 100 def data_download_thread(self, db_class, db_flag, experiment_type, data_type): self.pb.start() - self.setvar('prog-message', f'Download data from {db_flag}!!') - T = threading.Thread(target=self.data_download, args=(db_class, db_flag, experiment_type, data_type)) + self.setvar("prog-message", f"Download data from {db_flag}!!") + T = threading.Thread( + target=self.data_download, + args=(db_class, db_flag, experiment_type, data_type), + ) T.start() def remove_images(self): @@ -1713,21 +2232,36 @@ def remove_images(self): self.result_flag = False self.cluster_flag = False else: - Messagebox.show_warning(title="Attention", message='Waiting for model training!!!') + Messagebox.show_warning( + title="Attention", message="Waiting for model training!!!" + ) def get_trained_file_path(self): self.update_idletasks() self.trained_file_path = filedialog.askopenfilename() - print(f'trained_file_path is {self.trained_file_path}') - self.setvar('load', self.trained_file_path) + if not self.trained_file_path: # 如果用户取消文件选择 + print("No file selected.") + return + # 弹出确认对话框 + confirm = messagebox.askyesno( + title="Confirm File Import", + message="Ensure the imported file has been trained, or unexpected results may occur. Continue?", + ) + if confirm: + self.model_train_flag = True + print(f"trained_file_path is {self.trained_file_path}") + self.setvar("load", self.trained_file_path) + else: + print("File import cancelled.") + return def Select_files(self): files_show = ttk.Toplevel(self.bus_frm) files_show.title("Files select") - files_show.geometry('300x250') + files_show.geometry("300x250") frame0 = tk.Frame(files_show) frame0.pack() - path_label = tk.Label(frame0, text=f'Files in {self.multi_files}: ') + path_label = tk.Label(frame0, text=f"Files in {self.multi_files}: ") path_label.grid(row=0, column=0) frame1 = ttk.Frame(files_show) @@ -1737,11 +2271,11 @@ def Select_files(self): print(file_list) def getselect(item): - print(item, 'selected') + print(item, "selected") def unselectall(): for index, item in enumerate(list1): - v[index].set('') + v[index].set("") def selectall(): for index, item in enumerate(list1): @@ -1753,7 +2287,9 @@ def showselect(): self.multi_files = [os.path.join(self.multi_files, i) for i in selected] print(self.multi_files) files_show.destroy() - tk.messagebox.showwarning(title='Attention', message=f"you have selected {len(selected)} file!") + tk.messagebox.showwarning( + title="Attention", message=f"you have selected {len(selected)} file!" + ) self.path_load_flag = True canvas = tk.Canvas(files_show) @@ -1772,13 +2308,22 @@ def showselect(): for index, item in enumerate(list1): v.append(tk.StringVar()) - ttk.Checkbutton(frame2, text=item, variable=v[-1], onvalue=item, offvalue='', - command=lambda item=item: getselect(item)).grid(row=index, column=0, - sticky='w') - - seltone = ttk.Radiobutton(frame1, text='All', variable=opt, value=1, command=selectall) + ttk.Checkbutton( + frame2, + text=item, + variable=v[-1], + onvalue=item, + offvalue="", + command=lambda item=item: getselect(item), + ).grid(row=index, column=0, sticky="w") + + seltone = ttk.Radiobutton( + frame1, text="All", variable=opt, value=1, command=selectall + ) seltone.grid(row=0, column=0) - selttwo = ttk.Radiobutton(frame1, text='Cancel', variable=opt, value=0, command=unselectall) + selttwo = ttk.Radiobutton( + frame1, text="Cancel", variable=opt, value=0, command=unselectall + ) selttwo.grid(row=0, column=1) btn = ttk.Button(frame1, text="Confirm", command=showselect) btn.grid(row=0, column=2) @@ -1807,11 +2352,11 @@ def load_data(self): self.path_load_flag = False style = Style() style.configure("TCheckbutton", font=("Arial", 16)) - style.configure('TButton', font=('Arial', 16)) + style.configure("TButton", font=("Arial", 16)) self.Data_load_toplevel = ttk.Toplevel(self.backup) - self.Data_load_toplevel.attributes('-topmost', 'true') + self.Data_load_toplevel.attributes("-topmost", "true") self.Data_load_toplevel.title("Data Loading") - self.Data_load_toplevel.geometry('1000x450') + self.Data_load_toplevel.geometry("1000x450") self.radio_moduel = tk.Frame(self.Data_load_toplevel) self.radio_moduel.pack(side=TOP) @@ -1823,15 +2368,17 @@ def on_radio_select(value): self.path_load_flag = True self.load_moduel = tk.Frame(self.Data_load_toplevel) self.load_moduel.pack(after=self.radio_moduel) - file_label_one = ttk.Label(self.load_moduel, text="Count txt file path:", - font=('Arial', 16)) + file_label_one = ttk.Label( + self.load_moduel, text="Count txt file path:", font=("Arial", 16) + ) file_label_one.grid(row=0, column=0, padx=5, pady=5, sticky="w") file_entry_one = ttk.Entry(self.load_moduel) file_entry_one.grid(row=0, column=1, padx=5, pady=5) - file_label_two = ttk.Label(self.load_moduel, text="Location csv file path:", - font=('Arial', 16)) + file_label_two = ttk.Label( + self.load_moduel, text="Location csv file path:", font=("Arial", 16) + ) file_label_two.grid(row=1, column=0, padx=5, pady=5, sticky="w") file_entry_two = ttk.Entry(self.load_moduel) @@ -1847,38 +2394,54 @@ def browse_folder_two(): file_entry_two.delete(0, tk.END) file_entry_two.insert(0, folder_path) - confirm_button_one = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_one) + confirm_button_one = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_one, + ) confirm_button_one.grid(row=0, column=2, padx=5, pady=5) - confirm_button_two = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_two) + confirm_button_two = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_two, + ) confirm_button_two.grid(row=1, column=2, padx=5, pady=5) def load_datas(): - count = pd.read_csv(file_entry_one.get(), sep='\t', index_col=0) + count = pd.read_csv(file_entry_one.get(), sep="\t", index_col=0) location = pd.read_csv(file_entry_two.get(), index_col=0) adata = sc.AnnData(count.T) adata.var_names_make_unique() - coor_df = location.loc[adata.obs_names, ['xcoord', 'ycoord']] + coor_df = location.loc[adata.obs_names, ["xcoord", "ycoord"]] adata.obsm["spatial"] = coor_df.to_numpy() sc.pp.normalize_total(adata, target_sum=1e4) sc.pp.log1p(adata) sc.pp.calculate_qc_metrics(adata, inplace=True) path = file_entry_one.get() - adata.write_h5ad(path.rsplit('/', 1)[-2] + '/new_adata.h5ad') + adata.write_h5ad(path.rsplit("/", 1)[-2] + "/new_adata.h5ad") self.path_load_flag = False self.Data_load_toplevel.destroy() - Messagebox.show_warning(title="Attention", message='Files has been converted to h5ad!!!') + Messagebox.show_warning( + title="Attention", message="Files has been converted to h5ad!!!" + ) - confirm_button = ttk.Button(self.load_moduel, text="Confirm", style="TButton", command=load_datas) + confirm_button = ttk.Button( + self.load_moduel, + text="Confirm", + style="TButton", + command=load_datas, + ) confirm_button.grid(row=2, column=1, padx=5, pady=5) elif value == "h5_to_h5ad": self.path_load_flag = True self.load_moduel = tk.Frame(self.Data_load_toplevel) self.load_moduel.pack(after=self.radio_moduel) - file_label_one = ttk.Label(self.load_moduel, text="H5file folder Path:", - font=('Arial', 16)) + file_label_one = ttk.Label( + self.load_moduel, text="H5file folder Path:", font=("Arial", 16) + ) file_label_one.grid(row=0, column=0, padx=5, pady=5) file_entry = ttk.Entry(self.load_moduel) @@ -1889,38 +2452,53 @@ def browse_folder(): file_entry.delete(0, tk.END) file_entry.insert(0, folder_path) - confirm_button_one = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder) + confirm_button_one = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder, + ) confirm_button_one.grid(row=0, column=2, padx=5, pady=5) def load_datas(): - h5file = glob.glob(file_entry.get() + '/*.h5') - adata = sc.read_visium(path=file_entry.get(), count_file=h5file[0].rsplit("\\", 1)[-1]) + h5file = glob.glob(file_entry.get() + "/*.h5") + adata = sc.read_visium( + path=file_entry.get(), count_file=h5file[0].rsplit("\\", 1)[-1] + ) adata.var_names_make_unique() sc.pp.normalize_total(adata, target_sum=1e4) sc.pp.log1p(adata) sc.pp.calculate_qc_metrics(adata, inplace=True) - adata.write_h5ad(file_entry.get() + '/new_adata.h5ad') + adata.write_h5ad(file_entry.get() + "/new_adata.h5ad") self.path_load_flag = False self.Data_load_toplevel.destroy() - Messagebox.show_warning(title="Attention", message='Files has been converted to h5ad!!!') + Messagebox.show_warning( + title="Attention", message="Files has been converted to h5ad!!!" + ) - confirm_button = ttk.Button(self.load_moduel, text="Confirm", style="TButton", command=load_datas) + confirm_button = ttk.Button( + self.load_moduel, + text="Confirm", + style="TButton", + command=load_datas, + ) confirm_button.grid(row=2, column=1, padx=5, pady=5) elif value == "txt_to_h5ad" or value == "tsv_to_h5ad": self.path_load_flag = True self.load_moduel = tk.Frame(self.Data_load_toplevel) self.load_moduel.pack(after=self.radio_moduel) - file_label_one = ttk.Label(self.load_moduel, text="Count.tsv file Path:", - font=('Arial', 16)) + file_label_one = ttk.Label( + self.load_moduel, text="Count.tsv file Path:", font=("Arial", 16) + ) file_label_one.grid(row=0, column=0, padx=5, pady=5, sticky="w") file_entry_one = ttk.Entry(self.load_moduel) file_entry_one.grid(row=0, column=1, padx=5, pady=5) - file_label_two = ttk.Label(self.load_moduel, text="Location.tsv file Path:", - font=('Arial', 16)) + file_label_two = ttk.Label( + self.load_moduel, text="Location.tsv file Path:", font=("Arial", 16) + ) file_label_two.grid(row=1, column=0, padx=5, pady=5, sticky="w") file_entry_two = ttk.Entry(self.load_moduel) @@ -1936,16 +2514,24 @@ def browse_folder_two(): file_entry_two.delete(0, tk.END) file_entry_two.insert(0, folder_path) - confirm_button_one = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_one) + confirm_button_one = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_one, + ) confirm_button_one.grid(row=0, column=2, padx=5, pady=5) - confirm_button_two = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_two) + confirm_button_two = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_two, + ) confirm_button_two.grid(row=1, column=2, padx=5, pady=5) def load_datas(): - count = pd.read_csv(file_entry_one.get(), sep='\t') - location = pd.read_csv(file_entry_two.get(), sep='\t') + count = pd.read_csv(file_entry_one.get(), sep="\t") + location = pd.read_csv(file_entry_two.get(), sep="\t") adata = sc.AnnData(count) adata.var_names_make_unique() adata.obsm["spatial"] = location.to_numpy() @@ -1953,27 +2539,36 @@ def load_datas(): sc.pp.log1p(adata) path = file_entry_one.get() sc.pp.calculate_qc_metrics(adata, inplace=True) - adata.write_h5ad(path.rsplit('/', 1)[-2] + '/new_adata.h5ad') + adata.write_h5ad(path.rsplit("/", 1)[-2] + "/new_adata.h5ad") self.path_load_flag = False self.Data_load_toplevel.destroy() - Messagebox.show_warning(title="Attention", message='Files has been converted to h5ad!!!') + Messagebox.show_warning( + title="Attention", message="Files has been converted to h5ad!!!" + ) - confirm_button = ttk.Button(self.load_moduel, text="Confirm", style="TButton", command=load_datas) + confirm_button = ttk.Button( + self.load_moduel, + text="Confirm", + style="TButton", + command=load_datas, + ) confirm_button.grid(row=2, column=1, padx=5, pady=5) elif value == "SpatialDB_file_to_h5ad": self.path_load_flag = True self.load_moduel = tk.Frame(self.Data_load_toplevel) self.load_moduel.pack(after=self.radio_moduel) - file_label_one = ttk.Label(self.load_moduel, text="Count.count file Path:", - font=('Arial', 16)) + file_label_one = ttk.Label( + self.load_moduel, text="Count.count file Path:", font=("Arial", 16) + ) file_label_one.grid(row=0, column=0, padx=5, pady=5, sticky="w") file_entry_one = ttk.Entry(self.load_moduel) file_entry_one.grid(row=0, column=1, padx=5, pady=5) - file_label_two = ttk.Label(self.load_moduel, text="Location.idx file Path:", - font=('Arial', 16)) + file_label_two = ttk.Label( + self.load_moduel, text="Location.idx file Path:", font=("Arial", 16) + ) file_label_two.grid(row=1, column=0, padx=5, pady=5, sticky="w") file_entry_two = ttk.Entry(self.load_moduel) @@ -1989,59 +2584,103 @@ def browse_folder_two(): file_entry_two.delete(0, tk.END) file_entry_two.insert(0, folder_path) - confirm_button_one = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_one) + confirm_button_one = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_one, + ) confirm_button_one.grid(row=0, column=2, padx=5, pady=5) - confirm_button_two = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_two) + confirm_button_two = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_two, + ) confirm_button_two.grid(row=1, column=2, padx=5, pady=5) def load_datas(): - count = pd.read_csv(file_entry_one.get(), sep=',', index_col=0) + count = pd.read_csv(file_entry_one.get(), sep=",", index_col=0) count = count.T path = file_entry_one.get() - with open(path.rsplit('/', 1)[-2] + '/gene_id.txt', 'w') as f: + with open(path.rsplit("/", 1)[-2] + "/gene_id.txt", "w") as f: for item in list(count.columns): f.write("%s\n" % item) count.columns = count.iloc[0] count = count[1:] - location = pd.read_csv(file_entry_two.get(), sep=',', index_col=0) + location = pd.read_csv(file_entry_two.get(), sep=",", index_col=0) adata = sc.AnnData(count.values) adata.obs_names = [i for i in list(count.index)] adata.var_names = [i for i in list(count.columns)] - adata.obsm['spatial'] = location[['x', 'y']].values + adata.obsm["spatial"] = location[["x", "y"]].values # sc.pp.highly_variable_genes(adata, flavor="seurat_v3", n_top_genes=2000) sc.pp.normalize_total(adata, target_sum=1e4) sc.pp.log1p(adata) - adata.write_h5ad(path.rsplit('/', 1)[-2] + '/Transfor_new_data.h5ad') + adata.write_h5ad( + path.rsplit("/", 1)[-2] + "/Transfor_new_data.h5ad" + ) self.path_load_flag = False self.Data_load_toplevel.destroy() - Messagebox.show_warning(title="Attention", message='Files has been converted to h5ad!!!') + Messagebox.show_warning( + title="Attention", message="Files has been converted to h5ad!!!" + ) - confirm_button = ttk.Button(self.load_moduel, text="Confirm", style="TButton", command=load_datas) + confirm_button = ttk.Button( + self.load_moduel, + text="Confirm", + style="TButton", + command=load_datas, + ) confirm_button.grid(row=2, column=1, padx=5, pady=5) else: pass radio_var = tk.StringVar() - radio1 = ttk.Radiobutton(self.radio_moduel, text="Raw count txt and location csv to h5ad file", style="TCheckbutton", - variable=radio_var, - value="txt_csv_to_h5ad", command=lambda: on_radio_select("txt_csv_to_h5ad")) + radio1 = ttk.Radiobutton( + self.radio_moduel, + text="Raw count txt and location csv to h5ad file", + style="TCheckbutton", + variable=radio_var, + value="txt_csv_to_h5ad", + command=lambda: on_radio_select("txt_csv_to_h5ad"), + ) radio1.grid(row=0, column=0, padx=5, pady=5, sticky="w") - radio2 = ttk.Radiobutton(self.radio_moduel, text="Raw h5file to h5ad file", style="TCheckbutton", variable=radio_var, - value="h5_to_h5ad", command=lambda: on_radio_select("h5_to_h5ad")) + radio2 = ttk.Radiobutton( + self.radio_moduel, + text="Raw h5file to h5ad file", + style="TCheckbutton", + variable=radio_var, + value="h5_to_h5ad", + command=lambda: on_radio_select("h5_to_h5ad"), + ) radio2.grid(row=1, column=0, padx=5, pady=5, sticky="w") - radio3 = ttk.Radiobutton(self.radio_moduel, text="Raw count txt and location txt to h5ad file", style="TCheckbutton", - variable=radio_var, value="txt_to_h5ad", command=lambda: on_radio_select("txt_to_h5ad")) + radio3 = ttk.Radiobutton( + self.radio_moduel, + text="Raw count txt and location txt to h5ad file", + style="TCheckbutton", + variable=radio_var, + value="txt_to_h5ad", + command=lambda: on_radio_select("txt_to_h5ad"), + ) radio3.grid(row=2, column=0, padx=5, pady=5, sticky="w") - radio4 = ttk.Radiobutton(self.radio_moduel, text="Raw count tsv and location tsv to h5ad file", style="TCheckbutton", - variable=radio_var, value="tsv_to_h5ad", command=lambda: on_radio_select("tsv_to_h5ad")) + radio4 = ttk.Radiobutton( + self.radio_moduel, + text="Raw count tsv and location tsv to h5ad file", + style="TCheckbutton", + variable=radio_var, + value="tsv_to_h5ad", + command=lambda: on_radio_select("tsv_to_h5ad"), + ) radio4.grid(row=3, column=0, padx=5, pady=5, sticky="w") - radio5 = ttk.Radiobutton(self.radio_moduel, text="Raw count.count file and location.idx file to h5ad file", - style="TCheckbutton", - variable=radio_var, value="SpatialDB_file_to_h5ad", - command=lambda: on_radio_select("SpatialDB_file_to_h5ad")) + radio5 = ttk.Radiobutton( + self.radio_moduel, + text="Raw count.count file and location.idx file to h5ad file", + style="TCheckbutton", + variable=radio_var, + value="SpatialDB_file_to_h5ad", + command=lambda: on_radio_select("SpatialDB_file_to_h5ad"), + ) radio5.grid(row=4, column=0, padx=5, pady=5, sticky="w") def on_closing(): @@ -2051,22 +2690,31 @@ def on_closing(): self.Data_load_toplevel.protocol("WM_DELETE_WINDOW", on_closing) def Restart(self): - self.master.quit() - self.master.destroy() - python = sys.executable - subprocess.Popen([python] + sys.argv) + # 弹出确认对话框 + if messagebox.askyesno( + "Confirm Restart", + "Are you sure you want to restart? Please save your work.", + ): + messagebox.showinfo( + "Restarting", "The application is restarting. Please wait..." + ) + self.master.quit() + self.master.destroy() + python = sys.executable + module_name = "stabox.view.app" + subprocess.Popen([python, "-m", module_name]) def Preprocess(self): self.path_load_flag = False self.Data_load_toplevel = ttk.Toplevel(self.backup) - self.Data_load_toplevel.attributes('-topmost', 'true') + self.Data_load_toplevel.attributes("-topmost", "true") self.Data_load_toplevel.title("Data Preprocess") - self.Data_load_toplevel.geometry('550x320') + self.Data_load_toplevel.geometry("550x320") self.radio_moduel = tk.Frame(self.Data_load_toplevel) self.radio_moduel.pack(side=TOP) style = Style() style.configure("TCheckbutton", font=("Arial", 16)) - style.configure('TButton', font=('Arial', 16)) + style.configure("TButton", font=("Arial", 16)) def on_radio_select(value): if self.path_load_flag: @@ -2076,21 +2724,27 @@ def on_radio_select(value): self.path_load_flag = True self.load_moduel = tk.Frame(self.Data_load_toplevel) self.load_moduel.pack(after=self.radio_moduel) - file_label_one = ttk.Label(self.load_moduel, text="H5ad file path:", font=('Arial', 16)) # 创建Label控件 + file_label_one = ttk.Label( + self.load_moduel, text="H5ad file path:", font=("Arial", 16) + ) # 创建Label控件 file_label_one.grid(row=0, column=0, padx=5, pady=5, sticky="w") file_entry_one = ttk.Entry(self.load_moduel) # 创建Entry控件 file_entry_one.grid(row=0, column=1, padx=5, pady=5) - file_label_two = ttk.Label(self.load_moduel, text="Location csv file Path:", - font=('Arial', 16)) # 创建Label控件 + file_label_two = ttk.Label( + self.load_moduel, text="Location csv file Path:", font=("Arial", 16) + ) # 创建Label控件 file_label_two.grid(row=1, column=0, padx=5, pady=5, sticky="w") file_entry_two = ttk.Entry(self.load_moduel) # 创建Entry控件 file_entry_two.grid(row=1, column=1, padx=5, pady=5) - file_label_three = ttk.Label(self.load_moduel, text="Filter highly variable genes:", - font=('Arial', 16)) # 创建Label控件 + file_label_three = ttk.Label( + self.load_moduel, + text="Filter highly variable genes:", + font=("Arial", 16), + ) # 创建Label控件 file_label_three.grid(row=2, column=0, padx=5, pady=5, sticky="w") file_entry_three = ttk.Entry(self.load_moduel) # 创建Entry控件 @@ -2106,54 +2760,82 @@ def browse_folder_two(): file_entry_two.delete(0, tk.END) file_entry_two.insert(0, folder_path) - confirm_button_one = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_one) # 创建确认按钮 + confirm_button_one = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_one, + ) # 创建确认按钮 confirm_button_one.grid(row=0, column=2, padx=5, pady=5) - confirm_button_two = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_two) # 创建确认按钮 + confirm_button_two = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_two, + ) # 创建确认按钮 confirm_button_two.grid(row=1, column=2, padx=5, pady=5) def load_datas(): - adata = sc.read(file_entry_one.get(), sep='\t', index_col=0) - location = pd.read_csv(file_entry_two.get(), sep=',', index_col=0) + adata = sc.read(file_entry_one.get(), sep="\t", index_col=0) + location = pd.read_csv(file_entry_two.get(), sep=",", index_col=0) adata.var_names_make_unique() - coor_df = location.loc[adata.obs_names, ['x', 'y']] + coor_df = location.loc[adata.obs_names, ["x", "y"]] adata.obsm["spatial"] = coor_df.to_numpy() sc.pp.normalize_total(adata, target_sum=1e4) sc.pp.log1p(adata) sc.pp.calculate_qc_metrics(adata, inplace=True) if file_entry_three.get(): - sc.pp.highly_variable_genes(adata, flavor="seurat_v3", n_top_genes=int(file_entry_three.get())) - if 'highly_variable' in adata.var.columns: - adata = adata[:, adata.var['highly_variable']] + sc.pp.highly_variable_genes( + adata, + flavor="seurat_v3", + n_top_genes=int(file_entry_three.get()), + ) + if "highly_variable" in adata.var.columns: + adata = adata[:, adata.var["highly_variable"]] path = file_entry_one.get() - adata.write_h5ad(path.rsplit('/', 1)[-2] + '/new_adata.h5ad') + adata.write_h5ad(path.rsplit("/", 1)[-2] + "/new_adata.h5ad") self.path_load_flag = False self.Data_load_toplevel.destroy() - Messagebox.show_warning(title="Attention", message='Information has been added into h5ad files!!!') + Messagebox.show_warning( + title="Attention", + message="Information has been added into h5ad files!!!", + ) - confirm_button = ttk.Button(self.load_moduel, text="Confirm", style="TButton", command=load_datas) + confirm_button = ttk.Button( + self.load_moduel, + text="Confirm", + style="TButton", + command=load_datas, + ) confirm_button.grid(row=3, column=1, padx=5, pady=5) elif value == "add_GroundTurth": self.path_load_flag = True self.load_moduel = tk.Frame(self.Data_load_toplevel) self.load_moduel.pack(after=self.radio_moduel) - file_label_one = ttk.Label(self.load_moduel, text="H5ad file path:", font=('Arial', 16)) # 创建Label控件 + file_label_one = ttk.Label( + self.load_moduel, text="H5ad file path:", font=("Arial", 16) + ) # 创建Label控件 file_label_one.grid(row=0, column=0, padx=5, pady=5, sticky="w") file_entry_one = ttk.Entry(self.load_moduel) file_entry_one.grid(row=0, column=1, padx=5, pady=5) - file_label_two = ttk.Label(self.load_moduel, text="GroundTruth txt file Path:", - font=('Arial', 16)) # 创建Label控件 + file_label_two = ttk.Label( + self.load_moduel, + text="GroundTruth txt file Path:", + font=("Arial", 16), + ) # 创建Label控件 file_label_two.grid(row=1, column=0, padx=5, pady=5, sticky="w") file_entry_two = ttk.Entry(self.load_moduel) file_entry_two.grid(row=1, column=1, padx=5, pady=5) - file_label_three = ttk.Label(self.load_moduel, text="Filter highly variable genes:", - font=('Arial', 16)) # 创建Label控件 + file_label_three = ttk.Label( + self.load_moduel, + text="Filter highly variable genes:", + font=("Arial", 16), + ) # 创建Label控件 file_label_three.grid(row=2, column=0, padx=5, pady=5, sticky="w") file_entry_three = ttk.Entry(self.load_moduel) @@ -2169,48 +2851,77 @@ def browse_folder_two(): file_entry_two.delete(0, tk.END) file_entry_two.insert(0, folder_path) - confirm_button_one = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_one) # 创建确认按钮 + confirm_button_one = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_one, + ) # 创建确认按钮 confirm_button_one.grid(row=0, column=2, padx=5, pady=5) - confirm_button_two = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_two) # 创建确认按钮 + confirm_button_two = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_two, + ) # 创建确认按钮 confirm_button_two.grid(row=1, column=2, padx=5, pady=5) def load_datas(): adata = sc.read(file_entry_one.get()) adata.var_names_make_unique() - Ann_df = pd.read_csv(file_entry_two.get(), sep='\t', header=None, index_col=0) - Ann_df.columns = ['Ground Truth'] - adata.obs['GroundTruth'] = Ann_df.loc[adata.obs_names, 'Ground Truth'] + Ann_df = pd.read_csv( + file_entry_two.get(), sep="\t", header=None, index_col=0 + ) + Ann_df.columns = ["Ground Truth"] + adata.obs["GroundTruth"] = Ann_df.loc[ + adata.obs_names, "Ground Truth" + ] sc.pp.normalize_total(adata, target_sum=1e4) sc.pp.log1p(adata) sc.pp.calculate_qc_metrics(adata, inplace=True) if file_entry_three.get(): - sc.pp.highly_variable_genes(adata, flavor="seurat_v3", n_top_genes=int(file_entry_three.get())) - if 'highly_variable' in adata.var.columns: - adata = adata[:, adata.var['highly_variable']] + sc.pp.highly_variable_genes( + adata, + flavor="seurat_v3", + n_top_genes=int(file_entry_three.get()), + ) + if "highly_variable" in adata.var.columns: + adata = adata[:, adata.var["highly_variable"]] path = file_entry_one.get() - adata.write_h5ad(path.rsplit('/', 1)[-2] + '/new_adata.h5ad') + adata.write_h5ad(path.rsplit("/", 1)[-2] + "/new_adata.h5ad") del adata self.path_load_flag = False self.Data_load_toplevel.destroy() - Messagebox.show_warning(title="Attention", message='Information has been added into h5ad files!!!') + Messagebox.show_warning( + title="Attention", + message="Information has been added into h5ad files!!!", + ) - confirm_button = ttk.Button(self.load_moduel, text="Confirm", style="TButton", command=load_datas) + confirm_button = ttk.Button( + self.load_moduel, + text="Confirm", + style="TButton", + command=load_datas, + ) confirm_button.grid(row=3, column=1, padx=5, pady=5) else: self.path_load_flag = True self.load_moduel = tk.Frame(self.Data_load_toplevel) self.load_moduel.pack(after=self.radio_moduel) - file_label_one = ttk.Label(self.load_moduel, text="H5ad file path:", font=('Arial', 16)) # 创建Label控件 + file_label_one = ttk.Label( + self.load_moduel, text="H5ad file path:", font=("Arial", 16) + ) # 创建Label控件 file_label_one.grid(row=0, column=0, padx=5, pady=5, sticky="w") file_entry_one = ttk.Entry(self.load_moduel) file_entry_one.grid(row=0, column=1, padx=5, pady=5) - file_label_two = ttk.Label(self.load_moduel, text="Filter highly variable genes:", - font=('Arial', 16)) + file_label_two = ttk.Label( + self.load_moduel, + text="Filter highly variable genes:", + font=("Arial", 16), + ) file_label_two.grid(row=1, column=0, padx=5, pady=5, sticky="w") file_entry_two = ttk.Entry(self.load_moduel) @@ -2221,8 +2932,12 @@ def browse_folder_one(): file_entry_one.delete(0, tk.END) file_entry_one.insert(0, folder_path) - confirm_button_one = ttk.Button(self.load_moduel, text="Choose", style="TButton", - command=browse_folder_one) + confirm_button_one = ttk.Button( + self.load_moduel, + text="Choose", + style="TButton", + command=browse_folder_one, + ) confirm_button_one.grid(row=0, column=2, padx=5, pady=5) def load_datas(): @@ -2232,34 +2947,61 @@ def load_datas(): sc.pp.log1p(adata) sc.pp.calculate_qc_metrics(adata, inplace=True) if file_entry_two.get(): - sc.pp.highly_variable_genes(adata, flavor="seurat_v3", n_top_genes=int(file_entry_two.get())) - if 'highly_variable' in adata.var.columns: - adata = adata[:, adata.var['highly_variable']] + sc.pp.highly_variable_genes( + adata, + flavor="seurat_v3", + n_top_genes=int(file_entry_two.get()), + ) + if "highly_variable" in adata.var.columns: + adata = adata[:, adata.var["highly_variable"]] path = file_entry_one.get() - adata.write_h5ad(path.rsplit('/', 1)[-2] + '/new_adata.h5ad') + adata.write_h5ad(path.rsplit("/", 1)[-2] + "/new_adata.h5ad") self.path_load_flag = False self.Data_load_toplevel.destroy() - Messagebox.show_warning(title="Attention", message='Information has been added into h5ad files!!!') + Messagebox.show_warning( + title="Attention", + message="Information has been added into h5ad files!!!", + ) - confirm_button = ttk.Button(self.load_moduel, text="Confirm", style="TButton", command=load_datas) + confirm_button = ttk.Button( + self.load_moduel, + text="Confirm", + style="TButton", + command=load_datas, + ) confirm_button.grid(row=2, column=1, padx=5, pady=5) radio_var = tk.StringVar() - radio1 = ttk.Radiobutton(self.radio_moduel, text="H5ad file add location csv information", style="TCheckbutton", - variable=radio_var, - value="add_location", command=lambda: on_radio_select("add_location")) + radio1 = ttk.Radiobutton( + self.radio_moduel, + text="H5ad file add location csv information", + style="TCheckbutton", + variable=radio_var, + value="add_location", + command=lambda: on_radio_select("add_location"), + ) radio1.grid(row=0, column=0, padx=5, pady=5, sticky="w") - radio2 = ttk.Radiobutton(self.radio_moduel, text="H5ad file add GroundTurth txt information", - style="TCheckbutton", variable=radio_var, - value="add_GroundTurth", command=lambda: on_radio_select("add_GroundTurth")) + radio2 = ttk.Radiobutton( + self.radio_moduel, + text="H5ad file add GroundTurth txt information", + style="TCheckbutton", + variable=radio_var, + value="add_GroundTurth", + command=lambda: on_radio_select("add_GroundTurth"), + ) radio2.grid(row=1, column=0, padx=5, pady=5, sticky="w") # radio3 = ttk.Radiobutton(self.radio_moduel, text="Multiple h5ad conversions to STAligner input format", # style="TCheckbutton", variable=radio_var, # value="multiple_h5ad_files", command=lambda: on_radio_select("multiple_h5ad_files")) # radio3.grid(row=2, column=0, padx=5, pady=5, sticky="w") - radio3 = ttk.Radiobutton(self.radio_moduel, text="Only filter top genes and normalization data", - style="TCheckbutton", variable=radio_var, - value="filter_top_n", command=lambda: on_radio_select("filter_top_n")) + radio3 = ttk.Radiobutton( + self.radio_moduel, + text="Only filter top genes and normalization data", + style="TCheckbutton", + variable=radio_var, + value="filter_top_n", + command=lambda: on_radio_select("filter_top_n"), + ) radio3.grid(row=2, column=0, padx=5, pady=5, sticky="w") def on_closing(): @@ -2272,12 +3014,26 @@ def ShutdowmSoftware(self): sys.exit() def web_Server_Thread(self, data_save_path, ports=8050): - T = threading.Thread(target=webServer, args=(data_save_path, ports,)) + T = threading.Thread( + target=webServer, + args=( + data_save_path, + ports, + ), + ) T.setDaemon(True) T.start() def web_Thread(self, filepath, inh5data_, conf_file_, data_name): - T = threading.Thread(target=webcache_main, args=(filepath, inh5data_, conf_file_, data_name,)) + T = threading.Thread( + target=webcache_main, + args=( + filepath, + inh5data_, + conf_file_, + data_name, + ), + ) T.setDaemon(True) T.start() @@ -2290,119 +3046,257 @@ def web_Thread(self, filepath, inh5data_, conf_file_, data_name): def STAGATE_show(self): if self.cluster_flag: self.result_flag = True - plt.rcParams['font.sans-serif'] = "Arial" - self.gene_color_type = 'viridis' + plt.rcParams["font.sans-serif"] = "Arial" + self.gene_color_type = "viridis" if not self.data_type: - self.data_type = '10x' + self.data_type = "10x" def draw_images(): i = 1 os.chdir(Raw_PATH) from matplotlib import pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) - path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + path = os.path.join(test_file_path, "figures", f"{self.method_flag}_{self.data_type}") + print("label_files_exit:", self.label_files_exit) if self.label_files_exit: - sc.pl.spatial(adata, img_key="hires", color="GroundTruth", title='Ground Truth', show=False, - save='STAGATE_' + str(i) + '.png', spot_size=self.spot_size) - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', path + '/STAGATE_GroundTruth.png') + sc.pl.spatial( + adata, + img_key="hires", + color="GroundTruth", + title="Ground Truth", + show=False, + save="STAGATE_" + str(i) + ".png", + spot_size=self.spot_size, + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_GroundTruth.png", + ) i = i + 1 obs_df = adata.obs.dropna() - ARI = adjusted_rand_score(obs_df['mclust'], obs_df['GroundTruth']) + ARI = adjusted_rand_score(obs_df["mclust"], obs_df["GroundTruth"]) plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(adata, color="mclust", title=['STAGATE-mclust(ARI=%.2f)' % ARI], show=False, s=6, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGATE_' + str(i) + '.png', path + '/STAGATE_mclust_umap.png') + sc.pl.umap( + adata, + color="mclust", + title=["STAGATE-mclust(ARI=%.2f)" % ARI], + show=False, + s=6, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGATE_" + str(i) + ".png", + path + "/STAGATE_mclust_umap.png", + ) i = i + 1 - sc.pl.spatial(adata, color="mclust", title=['STAGATE-mclust(ARI=%.2f)' % ARI], show=False, - spot_size=self.spot_size, save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', - path + '/STAGATE_mclust.png') + sc.pl.spatial( + adata, + color="mclust", + title=["STAGATE-mclust(ARI=%.2f)" % ARI], + show=False, + spot_size=self.spot_size, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_mclust.png", + ) i = i + 1 - sc.pl.umap(adata, color="louvain", title=['STAGATE-louvain'], show=False, s=6, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGATE_' + str(i) + '.png', - path + '/STAGATE_louvain_umap.png') + sc.pl.umap( + adata, + color="louvain", + title=["STAGATE-louvain"], + show=False, + s=6, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGATE_" + str(i) + ".png", + path + "/STAGATE_louvain_umap.png", + ) i = i + 1 - sc.pl.spatial(adata, color="louvain", title=['STAGATE-louvain'], show=False, spot_size=self.spot_size, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', - path + '/STAGATE_louvain.png') + sc.pl.spatial( + adata, + color="louvain", + title=["STAGATE-louvain"], + show=False, + spot_size=self.spot_size, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_louvain.png", + ) i = i + 1 - sc.pl.umap(adata, color="STAGATE_kmeans", title=['STAGATE-kmeans'], show=False, s=6, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGATE_' + str(i) + '.png', - path + '/STAGATE_kmeans_umap.png') + sc.pl.umap( + adata, + color="STAGATE_kmeans", + title=["STAGATE-kmeans"], + show=False, + s=6, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGATE_" + str(i) + ".png", + path + "/STAGATE_kmeans_umap.png", + ) i = i + 1 - sc.pl.spatial(adata, color="STAGATE_kmeans", title=['STAGATE-kmeans'], show=False, spot_size=self.spot_size, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', - path + '/STAGATE_kmeans.png') + sc.pl.spatial( + adata, + color="STAGATE_kmeans", + title=["STAGATE-kmeans"], + show=False, + spot_size=self.spot_size, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_kmeans.png", + ) adata.obs.GroundTruth = adata.obs.GroundTruth.astype(str) i = i + 1 - sc.tl.paga(adata, groups='GroundTruth') + sc.tl.paga(adata, groups="GroundTruth") plt.rcParams["figure.figsize"] = (4, 3) - sc.pl.paga(adata, color="GroundTruth", title='PAGA', show=False, save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/pagaSTAGATE_' + str(i) + '.png', path + '/STAGATE_PAGA.png') + sc.pl.paga( + adata, + color="GroundTruth", + title="PAGA", + show=False, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/pagaSTAGATE_" + str(i) + ".png", + path + "/STAGATE_PAGA.png", + ) else: sc.pp.calculate_qc_metrics(adata, inplace=True) - sc.pl.spatial(adata, img_key="hires", color="log1p_total_counts", title='log1p_total_counts', - show=False, spot_size=self.spot_size, color_map=self.gene_color_type, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', - path + '/STAGATE_log1p_total_counts.png') + sc.pl.spatial( + adata, + img_key="hires", + color="log1p_total_counts", + title="log1p_total_counts", + show=False, + spot_size=self.spot_size, + color_map=self.gene_color_type, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_log1p_total_counts.png", + ) i = i + 1 - sc.pl.umap(adata, color="mclust", title=['STAGATE-Mclust'], show=False, s=6, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGATE_' + str(i) + '.png', - path + '/STAGATE_mclust_umap.png') + sc.pl.umap( + adata, + color="mclust", + title=["STAGATE-Mclust"], + show=False, + s=6, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGATE_" + str(i) + ".png", + path + "/STAGATE_mclust_umap.png", + ) i = i + 1 - sc.pl.spatial(adata, color="mclust", title=['STAGATE-Mclust'], show=False, spot_size=self.spot_size, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', - path + '/STAGATE_mclust.png') + sc.pl.spatial( + adata, + color="mclust", + title=["STAGATE-Mclust"], + show=False, + spot_size=self.spot_size, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_mclust.png", + ) i = i + 1 - sc.pl.umap(adata, color="louvain", title=['STAGATE-louvain'], show=False, s=6, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGATE_' + str(i) + '.png', - path + '/STAGATE_louvain_umap.png') + sc.pl.umap( + adata, + color="louvain", + title=["STAGATE-louvain"], + show=False, + s=6, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGATE_" + str(i) + ".png", + path + "/STAGATE_louvain_umap.png", + ) i = i + 1 - sc.pl.spatial(adata, color="louvain", title=['STAGATE-louvain'], show=False, spot_size=self.spot_size, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', - path + '/STAGATE_louvain.png') + sc.pl.spatial( + adata, + color="louvain", + title=["STAGATE-louvain"], + show=False, + spot_size=self.spot_size, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_louvain.png", + ) i = i + 1 - sc.pl.umap(adata, color="STAGATE_kmeans", title=['STAGATE-kmeans'], show=False, s=6, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGATE_' + str(i) + '.png', - path + '/STAGATE_kmeans_umap.png') + sc.pl.umap( + adata, + color="STAGATE_kmeans", + title=["STAGATE-kmeans"], + show=False, + s=6, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGATE_" + str(i) + ".png", + path + "/STAGATE_kmeans_umap.png", + ) i = i + 1 - sc.pl.spatial(adata, color="STAGATE_kmeans", title=['STAGATE-kmeans'], show=False, spot_size=self.spot_size, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', - path + '/STAGATE_kmeans.png') - adata.write_h5ad(self.file_path.rsplit('/', 1)[-2] + '/' + self.method_flag + '_result.h5ad') - print(f'Result images are saved in : {test_file_path}/figures', ) - print(f'Result data are saved in : ', self.file_path.rsplit('/', 1)[-2]) + sc.pl.spatial( + adata, + color="STAGATE_kmeans", + title=["STAGATE-kmeans"], + show=False, + spot_size=self.spot_size, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_kmeans.png", + ) + adata.write_h5ad( + self.file_path.rsplit("/", 1)[-2] + + "/" + + self.method_flag + + "_result.h5ad" + ) + print( + f"Result images are saved in : {test_file_path}/figures", + ) + print(f"Result data are saved in : ", self.file_path.rsplit("/", 1)[-2]) def scoller(): - self.figure_ybar = ttk.Scrollbar(self.figure_Frame, orient=VERTICAL, cursor='draft_small') + self.figure_ybar = ttk.Scrollbar( + self.figure_Frame, orient=VERTICAL, cursor="draft_small" + ) self.figure_ybar.pack(side=RIGHT, fill=Y) self.figure_ybar.config(command=self.canvas.yview) - self.figure_xbar = ttk.Scrollbar(self.figure_Frame, orient=HORIZONTAL, cursor='draft_small') + self.figure_xbar = ttk.Scrollbar( + self.figure_Frame, orient=HORIZONTAL, cursor="draft_small" + ) self.figure_xbar.pack(side=BOTTOM, fill=X) self.figure_xbar.config(command=self.canvas.xview) @@ -2416,41 +3310,50 @@ def scoller(): self.show_frame.bind("", onFrameconfigure) def onFrameconfigure(event): - self.canvas.configure(scrollregion=self.canvas.bbox("all"), width=1000, height=650) + self.canvas.configure( + scrollregion=self.canvas.bbox("all"), width=1000, height=650 + ) def choose_color(): colorvalue = colorchooser.askcolor() color_list = [] color = colorvalue[1] print(color) - if 'louvain_colors' in adata.uns and 'STAGATE_kmeans_colors' in adata.uns: - color_lens = [adata.uns['louvain_colors'], adata.uns['mclust_colors'], adata.uns['STAGATE_kmeans_colors']] + if ( + "louvain_colors" in adata.uns + and "STAGATE_kmeans_colors" in adata.uns + ): + color_lens = [ + adata.uns["louvain_colors"], + adata.uns["mclust_colors"], + adata.uns["STAGATE_kmeans_colors"], + ] max_len = max(color_lens, key=len) else: - max_len = adata.uns['mclust_colors'] + max_len = adata.uns["mclust_colors"] if len(max_len) > self.Mcluster_num: self.Mcluster_num = len(max_len) - if color[1:3] == 'ff': + if color[1:3] == "ff": color_list.append(color) list = random.sample(color_panel.FF_color, self.Mcluster_num) color_list = color_list + list - elif color[1:3] == 'cc': + elif color[1:3] == "cc": color_list.append(color) list = random.sample(color_panel.CC_color, self.Mcluster_num) color_list = color_list + list - elif color[1:3] == '99': + elif color[1:3] == "99": color_list.append(color) list = random.sample(color_panel.NN_color, self.Mcluster_num) color_list = color_list + list - elif color[1:3] == '66': + elif color[1:3] == "66": color_list.append(color) list = random.sample(color_panel.SS_color, self.Mcluster_num) color_list = color_list + list - elif color[1:3] == '33': + elif color[1:3] == "33": color_list.append(color) list = random.sample(color_panel.TT_color, self.Mcluster_num) color_list = color_list + list - elif color[1:3] == '00': + elif color[1:3] == "00": color_list.append(color) list = random.sample(color_panel.ZZ_color, self.Mcluster_num) color_list = color_list + list @@ -2461,29 +3364,57 @@ def choose_color(): print(color_list) if self.label_files_exit: - adata.uns['GroundTruth_colors'] = color_list[:len(adata.uns['GroundTruth_colors'])] - adata.uns['mclust_colors'] = color_list[:len(adata.uns['mclust_colors'])] - if 'louvain_colors' in adata.uns and 'STAGATE_kmeans_colors' in adata.uns: - adata.uns['louvain_colors'] = color_list[:len(adata.uns['louvain_colors'])] - adata.uns['STAGATE_kmeans_colors'] = color_list[:len(adata.uns['STAGATE_kmeans_colors'])] + adata.uns["GroundTruth_colors"] = color_list[ + : len(adata.uns["GroundTruth_colors"]) + ] + adata.uns["mclust_colors"] = color_list[ + : len(adata.uns["mclust_colors"]) + ] + if ( + "louvain_colors" in adata.uns + and "STAGATE_kmeans_colors" in adata.uns + ): + adata.uns["louvain_colors"] = color_list[ + : len(adata.uns["louvain_colors"]) + ] + adata.uns["STAGATE_kmeans_colors"] = color_list[ + : len(adata.uns["STAGATE_kmeans_colors"]) + ] self.color_reset = color_list self.gene_color_type = color_panel.five_gene_color[random.randint(0, 5)] os.chdir(Raw_PATH) draw_images() - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + fig_path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + ) figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0) - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type - if not os.path.isdir(fig_path): - os.mkdir(fig_path) - + fig_path = os.path.join(test_file_path, "figures", f"{self.method_flag}_{self.data_type}") + # 创建目录,如果目录已存在,清空目录中的所有文件 + if os.path.exists(fig_path): + # 清空目录中的所有文件 + for filename in os.listdir(fig_path): + file_path = os.path.join(fig_path, filename) + try: + if os.path.isfile(file_path) or os.path.islink(file_path): + os.unlink(file_path) # 删除文件或符号链接 + elif os.path.isdir(file_path): + shutil.rmtree(file_path) # 删除文件夹及其内容 + except Exception as e: + print(f'Failed to delete {file_path}. Reason: {e}') + else: + os.makedirs(fig_path, exist_ok=True) # 如果目录不存在,创建目录 adata = self.result_queue.get() self.result_queue.put(adata) # adata = mclust_R(adata, used_obsm='STAGATE', num_cluster=self.Mcluster_num) @@ -2493,7 +3424,7 @@ def choose_color(): # adata.obs['STAGATE_kmeans'] = kmeans.labels_ # adata.obs['STAGATE_kmeans'] = adata.obs['STAGATE_kmeans'].astype('category') if self.label_files_exit: - adata = adata[adata.obs['GroundTruth'] == adata.obs['GroundTruth'],] + adata = adata[adata.obs["GroundTruth"] == adata.obs["GroundTruth"],] else: adata.obsm["spatial"] = adata.obsm["spatial"] * (-1) draw_images() @@ -2504,114 +3435,204 @@ def choose_color(): self.show_frame = ttk.Frame(self.canvas) scoller() - self.set_frame = ttk.Frame(self.figure_Frame, borderwidth=2, relief="sunken") - self.set_frame.pack(side='right', expand=YES, anchor=N) + self.set_frame = ttk.Frame( + self.figure_Frame, borderwidth=2, relief="sunken" + ) + self.set_frame.pack(side="right", expand=YES, anchor=N) self.set_frame_one = ttk.Frame(self.set_frame) self.set_frame_one.pack(side=TOP, expand=YES) self.set_frame_two = ttk.Frame(self.set_frame) self.set_frame_two.pack(side=TOP, expand=YES) - self.Reset = ttk.Button(self.set_frame_one, text='Reset all colors', command=choose_color, width=12) + self.Reset = ttk.Button( + self.set_frame_one, + text="Reset all colors", + command=choose_color, + width=12, + ) self.Reset.grid(row=0, column=0, sticky=W, pady=0, padx=0) - self.domain_color_label = ttk.Label(self.set_frame_one, text='Reset domain color: ', width=20) + self.domain_color_label = ttk.Label( + self.set_frame_one, text="Reset domain color: ", width=20 + ) self.domain_color_label.grid(row=1, column=0, sticky=W, pady=0) self.Reset_domain_color = ttk.Entry(self.set_frame_one, width=10) self.Reset_domain_color.grid(row=1, column=1, sticky=W, pady=0) - Tooltip(self.Reset_domain_color, "Input value must be int type and in [1:cluster_name]: 2") + Tooltip( + self.Reset_domain_color, + "Input value must be int type and in [1:cluster_name]: 2", + ) self.color_update = None def Reset_single_domain_color(): from tkinter import colorchooser, filedialog + colorvalue = colorchooser.askcolor() color = colorvalue[1] print(color) cluster = self.Reset_domain_color.get() print(cluster) - adata.uns['mclust_colors'] = self.color_reset[:len(adata.uns['mclust_colors'])] - adata.uns['mclust_colors'][int(cluster) - 1] = color - if 'louvain_colors' in adata.uns: - adata.uns['louvain_colors'] = self.color_reset[:len(adata.uns['louvain_colors'])] - adata.uns['louvain_colors'][int(cluster) - 1] = color + adata.uns["mclust_colors"] = self.color_reset[ + : len(adata.uns["mclust_colors"]) + ] + adata.uns["mclust_colors"][int(cluster) - 1] = color + if "louvain_colors" in adata.uns: + adata.uns["louvain_colors"] = self.color_reset[ + : len(adata.uns["louvain_colors"]) + ] + adata.uns["louvain_colors"][int(cluster) - 1] = color self.color_reset[int(cluster) - 1] = color self.color_update = self.color_reset print(f"adata.uns['mclust_colors'] = {adata.uns['mclust_colors']}") import matplotlib.pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) i = 1 - path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + ) if self.label_files_exit: i = i + 1 obs_df = adata.obs.dropna() - ARI = adjusted_rand_score(obs_df['mclust'], obs_df['GroundTruth']) + ARI = adjusted_rand_score(obs_df["mclust"], obs_df["GroundTruth"]) plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(adata, color="mclust", title=['STAGATE (ARI=%.2f)' % ARI], show=False, s=6, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGATE_' + str(i) + '.png', path + '/STAGATE_' + str(i) + '.png') + sc.pl.umap( + adata, + color="mclust", + title=["STAGATE (ARI=%.2f)" % ARI], + show=False, + s=6, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGATE_" + str(i) + ".png", + path + "/STAGATE_" + str(i) + ".png", + ) i = i + 1 - sc.pl.spatial(adata, color="mclust", title=['STAGATE (ARI=%.2f)' % ARI], show=False, - spot_size=150, save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', path + '/STAGATE_' + str(i) + '.png') + sc.pl.spatial( + adata, + color="mclust", + title=["STAGATE (ARI=%.2f)" % ARI], + show=False, + spot_size=150, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_" + str(i) + ".png", + ) else: i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(adata, color="mclust", title=['STAGATE'], show=False, s=6, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGATE_' + str(i) + '.png', - path + '/STAGATE_' + str(i) + '.png') + sc.pl.umap( + adata, + color="mclust", + title=["STAGATE"], + show=False, + s=6, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGATE_" + str(i) + ".png", + path + "/STAGATE_" + str(i) + ".png", + ) i = i + 1 - sc.pl.spatial(adata, color="mclust", title=['STAGATE'], show=False, - spot_size=150, save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', path + '/STAGATE_' + str(i) + '.png') + sc.pl.spatial( + adata, + color="mclust", + title=["STAGATE"], + show=False, + spot_size=150, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_" + str(i) + ".png", + ) i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(adata, color="louvain", title=['STAGATE-louvain'], show=False, s=6, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGATE_' + str(i) + '.png', - path + '/STAGATE_' + str(i) + '.png') + sc.pl.umap( + adata, + color="louvain", + title=["STAGATE-louvain"], + show=False, + s=6, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGATE_" + str(i) + ".png", + path + "/STAGATE_" + str(i) + ".png", + ) i = i + 1 - sc.pl.spatial(adata, color="louvain", title=['STAGATE-louvain'], show=False, spot_size=150, - save='STAGATE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAGATE_' + str(i) + '.png', - path + '/STAGATE_' + str(i) + '.png') + sc.pl.spatial( + adata, + color="louvain", + title=["STAGATE-louvain"], + show=False, + spot_size=150, + save="STAGATE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAGATE_" + str(i) + ".png", + path + "/STAGATE_" + str(i) + ".png", + ) figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - img = Image.open(fig_path + '/' + figures[i]) + img = Image.open(fig_path + "/" + figures[i]) print(img.size) - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) - self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0, padx=0) + self.result_images.grid( + row=i // 3, column=i % 3, sticky=W, pady=0, padx=0 + ) s = i - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Confirm', - command=Reset_single_domain_color) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, + width=10, + text="Confirm", + command=Reset_single_domain_color, + ) self.Reset_domain_btn.grid(row=1, column=2, sticky=W, pady=10) - self.update_image_label = ttk.Label(self.set_frame_one, text='Reset image dpi: ', width=20) + self.update_image_label = ttk.Label( + self.set_frame_one, text="Reset image dpi: ", width=20 + ) self.update_image_label.grid(row=2, column=0, sticky=W, pady=10) self.update_image_scale = ttk.Entry(self.set_frame_one, width=10) self.update_image_scale.grid(row=2, column=1, sticky=W, pady=10) - Tooltip(self.update_image_scale, "Input value must be int type and >= 300: 300") + Tooltip( + self.update_image_scale, "Input value must be int type and >= 300: 300" + ) def ipdate_hd(): dpi = self.update_image_scale.get() print(dpi) import matplotlib.pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) sc.set_figure_params(dpi=dpi) draw_images() figures = os.listdir(fig_path) print(len(figures)) - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Save', command=ipdate_hd) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, width=10, text="Save", command=ipdate_hd + ) self.Reset_domain_btn.grid(row=2, column=2, sticky=W, pady=0) - self.gene_visualization_label = ttk.Label(self.set_frame_one, text='Input gene name: ', width=20) + self.gene_visualization_label = ttk.Label( + self.set_frame_one, text="Input gene name: ", width=20 + ) self.gene_visualization_label.grid(row=3, column=0, sticky=W, pady=0) self.gene_visualization_entry = ttk.Entry(self.set_frame_one, width=10) @@ -2621,27 +3642,36 @@ def ipdate_hd(): def gene_visualization(): gene = self.gene_visualization_entry.get() if gene not in adata.var_names: - print(f'{gene} is mot in adata!!Please input right gene name!') - sc.pl.spatial(adata, img_key="hires", color=gene, title="$" + gene + "$", spot_size=150, show=False, - save=gene + '.png') + print(f"{gene} is mot in adata!!Please input right gene name!") + sc.pl.spatial( + adata, + img_key="hires", + color=gene, + title="$" + gene + "$", + spot_size=150, + show=False, + save=gene + ".png", + ) global img0 - photo = Image.open(test_file_path + '/figures/show' + gene + '.png') + photo = Image.open(test_file_path + "/figures/show" + gene + ".png") img0 = ImageTk.PhotoImage(photo) img1 = ttk.Label(self.set_frame_two, image=img0) img1.grid(row=0, column=0, sticky=W, pady=0) - if os.path.exists(test_file_path + '/figures/show' + gene + '.png'): - os.remove(test_file_path + '/figures/show' + gene + '.png') + if os.path.exists(test_file_path + "/figures/show" + gene + ".png"): + os.remove(test_file_path + "/figures/show" + gene + ".png") print("yes") else: print("error!") - self.gene_visualization_btn = ttk.Button(self.set_frame_one, width=10, command=gene_visualization, text='Show') + self.gene_visualization_btn = ttk.Button( + self.set_frame_one, width=10, command=gene_visualization, text="Show" + ) self.gene_visualization_btn.grid(row=3, column=2, sticky=W, pady=0) figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0) s = i @@ -2652,15 +3682,20 @@ def gene_visualization(): def VIEW_3D(): import webbrowser + self.web_Server_Thread("/DLPFC/webcache", int(self.Entry.get())) - http = 'http://127.0.0.1:' + self.Entry.get() + '/' + http = "http://127.0.0.1:" + self.Entry.get() + "/" # 'http://127.0.0.1:8050/' webbrowser.open(http) - self.Reset = ttk.Button(self.set_frame_one, text='3D VIEW', command=VIEW_3D, width=10) + self.Reset = ttk.Button( + self.set_frame_one, text="3D VIEW", command=VIEW_3D, width=10 + ) self.Reset.grid(row=0, column=2, sticky=W, pady=0) else: - Messagebox.show_warning(title="Attention", message='Waiting for model training!!!') + Messagebox.show_warning( + title="Attention", message="Waiting for model training!!!" + ) def get_directory(self): """Open dialogue to get directory and update variable""" @@ -2668,7 +3703,7 @@ def get_directory(self): self.file_path = filedialog.askopenfilename() print(self.file_path) if self.file_path: - self.setvar('folder-path', self.file_path) + self.setvar("folder-path", self.file_path) if self.path_load_flag: self.path_load_flag = False @@ -2684,34 +3719,42 @@ def Visium_data_process(self): adj_list = [] key_add = [] for i in self.multi_files: - file_name = i.rsplit('\\', 1)[-1] - key_add.append(file_name.rsplit('.', 1)[-2]) + file_name = i.rsplit("\\", 1)[-1] + key_add.append(file_name.rsplit(".", 1)[-2]) adata_ = sc.read_h5ad(i) adata_.X = csr_matrix(adata_.X) adata_.var_names_make_unique(join="++") sc.pp.filter_genes(adata_, min_cells=50) - adata_.obs_names = [x + '_' + file_name.rsplit('.', 1)[-2] for x in adata_.obs_names] + adata_.obs_names = [ + x + "_" + file_name.rsplit(".", 1)[-2] for x in adata_.obs_names + ] Cal_Spatial_Net_new(adata_, rad_cutoff=self.rad_cutoff_value) - sc.pp.highly_variable_genes(adata_, flavor="seurat_v3", n_top_genes=5000) - if 'highly_variable' in adata_.var.columns: - adata_ = adata_[:, adata_.var['highly_variable']] + sc.pp.highly_variable_genes( + adata_, flavor="seurat_v3", n_top_genes=5000 + ) + if "highly_variable" in adata_.var.columns: + adata_ = adata_[:, adata_.var["highly_variable"]] sc.pp.normalize_total(adata_, target_sum=1e4) sc.pp.log1p(adata_) - adj_list.append(adata_.uns['adj']) + adj_list.append(adata_.uns["adj"]) Batch_list.append(adata_) adata = ad.concat(Batch_list, label="slice_name", keys=key_add) - adata.obs["batch_name"] = adata.obs["slice_name"].astype('category') + adata.obs["batch_name"] = adata.obs["slice_name"].astype("category") adj_concat = np.asarray(adj_list[0].todense()) for batch_id in range(1, len(self.multi_files)): - adj_concat = scipy.linalg.block_diag(adj_concat, np.asarray(adj_list[batch_id].todense())) - adata.uns['edgeList'] = np.nonzero(adj_concat) + adj_concat = scipy.linalg.block_diag( + adj_concat, np.asarray(adj_list[batch_id].todense()) + ) + adata.uns["edgeList"] = np.nonzero(adj_concat) else: adata = sc.read(self.file_path) adata.var_names_make_unique() sc.pp.normalize_total(adata, target_sum=1e4) sc.pp.log1p(adata) - self.paned_window = tk.PanedWindow(self.right_panel, orient=tk.HORIZONTAL, sashrelief=tk.SUNKEN, height=100) + self.paned_window = tk.PanedWindow( + self.right_panel, orient=tk.HORIZONTAL, sashrelief=tk.SUNKEN, height=100 + ) self.paned_window.pack(fill=X, before=self.info_Frame) text_widget = ttk.Text(self.paned_window) self.paned_window.add(text_widget) @@ -2725,7 +3768,7 @@ def Visium_data_process(self): print(f"Sequencing data platform is : NO choose(default 10x)") # print(f"Data type is : {type(adata)}") print(f"Data size is : {adata.shape[0]}*{adata.shape[1]}") - if 'GroundTruth' in adata.obs.columns: + if "GroundTruth" in adata.obs.columns: print(f"Whether Ground Truth is in Data : YES") else: print(f"Whether Ground Truth is in Data : NO") @@ -2758,58 +3801,74 @@ def Run_STAGATE(self): self.model_train_flag = False self.cluster_flag = False adata = self.result_queue.get() - if 'GroundTruth' in adata.obs.columns: - # if 'GroundTruth' in adata.obs.columns or 'GroundTruth_colors' in adata.uns.columns: + if "GroundTruth" in adata.obs.columns: + # if 'GroundTruth' in adata.obs.columns or 'GroundTruth_colors' in adata.uns.columns: self.label_files_exit = True - if 'STAGATE' not in adata.obsm: - data_save_path = running_path + '/result/' + if "STAGATE" not in adata.obsm: + data_save_path = running_path + "/result/" Cal_Spatial_Net(adata, float(self.rad_cutoff_value)) Stats_Spatial_Net(adata) if adata.shape[1] < int(self.alpha_value): self.alpha_value = adata.shape[1] - stagate = STAGATE(model_dir=data_save_path, - in_features=self.alpha_value, hidden_dims=[512, 30]) - print("self.alpha_value",self.alpha_value) + stagate = STAGATE( + model_dir=data_save_path, + in_features=self.alpha_value, + hidden_dims=[512, 30], + ) + print("self.alpha_value", self.alpha_value) print("self.cluster_value", self.cluster_value) print("self.genes", self.genes) print("self.rad_cutof", float(self.rad_cutoff.get())) print("self.genes", float(self.gene_name.get())) print("self.cluster_value", int(self.cluster.get())) - adata = stagate.train(adata, n_epochs=int(self.cluster_value), lr=float(self.genes)) - sc.pp.neighbors(adata, use_rep='STAGATE') + adata = stagate.train( + adata, n_epochs=int(self.cluster_value), lr=float(self.genes) + ) + sc.pp.neighbors(adata, use_rep="STAGATE") sc.tl.umap(adata) # adata = mclust_R(adata, used_obsm='STAGATE', num_cluster=self.cluster_value) # sc.tl.louvain(adata, resolution=self.alpha_value) - data_save_path = test_file_path + '/DLPFC' + data_save_path = test_file_path + "/DLPFC" if not os.path.exists(data_save_path): os.makedirs(data_save_path) - adata.write_h5ad(os.path.join(data_save_path, 'DLPFC.h5ad')) + adata.write_h5ad(os.path.join(data_save_path, "DLPFC.h5ad")) json_file = { "Coordinate": "spatial", "Annotatinos": ["mclust"], - "Meshes": { - }, + "Meshes": {}, "mesh_coord": "fixed.json", - "Genes": [ - "all" - ] + "Genes": ["all"], } - fixed_file = {"xmin": 0, "ymin": 0, "margin": 0, "zmin": 0, "binsize": 1} - json.dump(json_file, open(os.path.join(data_save_path, 'DLPFC.json'), 'w'), indent=4) - json.dump(fixed_file, open(os.path.join(data_save_path, 'fixed.json'), 'w')) - self.web_Thread(data_save_path, 'DLPFC.h5ad', 'DLPFC.json', 'Single-DLPFC') + fixed_file = { + "xmin": 0, + "ymin": 0, + "margin": 0, + "zmin": 0, + "binsize": 1, + } + json.dump( + json_file, + open(os.path.join(data_save_path, "DLPFC.json"), "w"), + indent=4, + ) + json.dump( + fixed_file, open(os.path.join(data_save_path, "fixed.json"), "w") + ) + self.web_Thread( + data_save_path, "DLPFC.h5ad", "DLPFC.json", "Single-DLPFC" + ) - data_path = os.path.join(running_path ,"result", "STAGATE_output.h5ad") + data_path = os.path.join(running_path, "result", "STAGATE_output.h5ad") adata.write_h5ad(data_path) print(f"File is saved in :{data_path}") # self.result_queue.put(adata) self.pb.stop() - self.pb['value'] = 100 - self.setvar('prog-message', 'STAGATE run over!') - self.setvar('End-time', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + self.pb["value"] = 100 + self.setvar("prog-message", "STAGATE run over!") + self.setvar("End-time", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) EndTime = datetime.now().replace(microsecond=0) - self.setvar('total-time-cost', EndTime - self.StartTime) + self.setvar("total-time-cost", EndTime - self.StartTime) self.model_train_flag = True self.cluster_flag = True @@ -2835,87 +3894,179 @@ def STAligner_show(self): # resolution=float(self.louvain_res)) # mclust_R(adata_new, num_cluster=int(self.Mcluster_num), used_obsm='STAligner') for section_id in self.multi_files: - file_name = section_id.rsplit('\\', 1)[-1] - k = file_name.rsplit('.', 1)[-2] + file_name = section_id.rsplit("\\", 1)[-1] + k = file_name.rsplit(".", 1)[-2] key_add.append(k) for section_id in key_add: - Batch_list.append(adata_new[adata_new.obs['batch_name'] == section_id]) + Batch_list.append(adata_new[adata_new.obs["batch_name"] == section_id]) def draw_images(): os.chdir(Raw_PATH) from matplotlib import pyplot as plt - plt.rcParams['font.sans-serif'] = "Arial" - path = test_file_path + '/figures/' + self.method_flag + '_output/' + + plt.rcParams["font.sans-serif"] = "Arial" + path = test_file_path + "/figures/" + self.method_flag + "_output/" if self.label_files_exit: i = 1 k = 1 for section_id in key_add: plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.spatial(adata_list[section_id], img_key="hires", color=["GroundTruth"], - title=section_id + "-Ground Truth", - show=False, save='STAligner_' + str(k) + '_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/show' + 'STAligner_' + str(k) + '_' + str(i) + '.png', - path + 'STAligner_' + str(k) + '_' + str(i) + '_' + section_id + '_GroundTruth.png') + sc.pl.spatial( + adata_list[section_id], + img_key="hires", + color=["GroundTruth"], + title=section_id + "-Ground Truth", + show=False, + save="STAligner_" + str(k) + "_" + str(i) + ".png", + ) + shutil.move( + test_file_path + + "/figures/show" + + "STAligner_" + + str(k) + + "_" + + str(i) + + ".png", + path + + "STAligner_" + + str(k) + + "_" + + str(i) + + "_" + + section_id + + "_GroundTruth.png", + ) i = i + 1 k = k + 1 i = 1 for j in range(len(self.multi_files)): plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.spatial(Batch_list[j], color=['mclust'], title=f'Mclust-{key_add[j]}', - spot_size=self.spot_size, show=False, - save='STAligner_' + str(k) + '_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/show' + 'STAligner_' + str(k) + '_' + str(i) + '.png', - path + 'STAligner_' + str(k) + '_' + str(i) + '_Mclust.png') + sc.pl.spatial( + Batch_list[j], + color=["mclust"], + title=f"Mclust-{key_add[j]}", + spot_size=self.spot_size, + show=False, + save="STAligner_" + str(k) + "_" + str(i) + ".png", + ) + shutil.move( + test_file_path + + "/figures/show" + + "STAligner_" + + str(k) + + "_" + + str(i) + + ".png", + path + "STAligner_" + str(k) + "_" + str(i) + "_Mclust.png", + ) i = i + 1 k = k + 1 i = 1 for j in range(len(self.multi_files)): plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.spatial(Batch_list[j], color=['louvain'], title=f'louvain-{key_add[j]}', - spot_size=self.spot_size, show=False, - save='STAligner_' + str(k) + '_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/show' + 'STAligner_' + str(k) + '_' + str(i) + '.png', - path + 'STAligner_' + str(k) + '_' + str(i) + '_louvain.png') + sc.pl.spatial( + Batch_list[j], + color=["louvain"], + title=f"louvain-{key_add[j]}", + spot_size=self.spot_size, + show=False, + save="STAligner_" + str(k) + "_" + str(i) + ".png", + ) + shutil.move( + test_file_path + + "/figures/show" + + "STAligner_" + + str(k) + + "_" + + str(i) + + ".png", + path + + "STAligner_" + + str(k) + + "_" + + str(i) + + "_louvain.png", + ) i = i + 1 k = k + 1 i = 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(adata_new[~adata_new.obs['GroundTruth'].isin(['unknown'])], color=['batch_name'], - title='STAligner-Mclust', - show=False, s=6, save='STAligner_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAligner_' + str(i) + '.png', - path + 'STAligner_' + str(k) + '_' + str(i) + '_Batchsumap.png') + sc.pl.umap( + adata_new[~adata_new.obs["GroundTruth"].isin(["unknown"])], + color=["batch_name"], + title="STAligner-Mclust", + show=False, + s=6, + save="STAligner_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAligner_" + str(i) + ".png", + path + "STAligner_" + str(k) + "_" + str(i) + "_Batchsumap.png", + ) k = k + 1 plt.rcParams["figure.figsize"] = (3, 3) i = 1 - sc.pl.umap(adata_new[~adata_new.obs['GroundTruth'].isin(['unknown'])], color=['GroundTruth'], - title='Ground Truth', - show=False, s=6, save='STAligner_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAligner_' + str(i) + '.png', - path + 'STAligner_' + str(k) + '_' + str(i) + '_GroundTruthumap.png') + sc.pl.umap( + adata_new[~adata_new.obs["GroundTruth"].isin(["unknown"])], + color=["GroundTruth"], + title="Ground Truth", + show=False, + s=6, + save="STAligner_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAligner_" + str(i) + ".png", + path + + "STAligner_" + + str(k) + + "_" + + str(i) + + "_GroundTruthumap.png", + ) k = k + 1 plt.rcParams["figure.figsize"] = (3, 3) i = 1 - sc.pl.umap(adata_new, color=['louvain'], title='STAligner-louvain', - show=False, s=6, save='STAligner_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAligner_' + str(i) + '.png', - path + 'STAligner_' + str(k) + '_' + str(i) + '_louvain.png') + sc.pl.umap( + adata_new, + color=["louvain"], + title="STAligner-louvain", + show=False, + s=6, + save="STAligner_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAligner_" + str(i) + ".png", + path + "STAligner_" + str(k) + "_" + str(i) + "_louvain.png", + ) else: i = 1 k = 1 for j in range(len(self.multi_files)): plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.spatial(Batch_list[j], color=['mclust'], title='STAligner-mclust', - spot_size=self.spot_size, show=False, - save='STAligner_' + str(k) + '_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/show' + 'STAligner_' + str(k) + '_' + str(i) + '.png', - path + 'STAligner_' + str(k) + '_' + str(i) + '_mclust.png') + sc.pl.spatial( + Batch_list[j], + color=["mclust"], + title="STAligner-mclust", + spot_size=self.spot_size, + show=False, + save="STAligner_" + str(k) + "_" + str(i) + ".png", + ) + shutil.move( + test_file_path + + "/figures/show" + + "STAligner_" + + str(k) + + "_" + + str(i) + + ".png", + path + "STAligner_" + str(k) + "_" + str(i) + "_mclust.png", + ) i = i + 1 @@ -2923,38 +4074,75 @@ def draw_images(): i = 1 for j in range(len(self.multi_files)): plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.spatial(Batch_list[j], color=['louvain'], title=f'louvain-{key_add[j]}', - spot_size=self.spot_size, show=False, - save='STAligner_' + str(k) + '_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/show' + 'STAligner_' + str(k) + '_' + str(i) + '.png', - path + 'STAligner_' + str(k) + '_' + str(i) + '_louvain.png') + sc.pl.spatial( + Batch_list[j], + color=["louvain"], + title=f"louvain-{key_add[j]}", + spot_size=self.spot_size, + show=False, + save="STAligner_" + str(k) + "_" + str(i) + ".png", + ) + shutil.move( + test_file_path + + "/figures/show" + + "STAligner_" + + str(k) + + "_" + + str(i) + + ".png", + path + + "STAligner_" + + str(k) + + "_" + + str(i) + + "_louvain.png", + ) i = i + 1 k = k + 1 i = 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(adata_new[~adata_new.obs['GroundTruth'].isin(['unknown'])], color=['batch_name'], - title='STAligner-Mclust', - show=False, s=6, save='STAligner_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAligner_' + str(i) + '.png', - path + 'STAligner_' + str(k) + '_' + str(i) + '_Batchsumap.png') + sc.pl.umap( + adata_new[~adata_new.obs["GroundTruth"].isin(["unknown"])], + color=["batch_name"], + title="STAligner-Mclust", + show=False, + s=6, + save="STAligner_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAligner_" + str(i) + ".png", + path + "STAligner_" + str(k) + "_" + str(i) + "_Batchsumap.png", + ) k = k + 1 plt.rcParams["figure.figsize"] = (3, 3) i = 1 - sc.pl.umap(adata_new, color=['louvain'], title='STAligner-louvain', - show=False, s=6, save='STAligner_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAligner_' + str(i) + '.png', - path + 'STAligner_' + str(k) + '_' + str(i) + '_louvain.png') - print(f'Result images are saved in : {test_file_path}/figures') + sc.pl.umap( + adata_new, + color=["louvain"], + title="STAligner-louvain", + show=False, + s=6, + save="STAligner_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAligner_" + str(i) + ".png", + path + "STAligner_" + str(k) + "_" + str(i) + "_louvain.png", + ) + print(f"Result images are saved in : {test_file_path}/figures") def scoller(): - self.figure_ybar = ttk.Scrollbar(self.figure_Frame, orient=VERTICAL, cursor='draft_small') + self.figure_ybar = ttk.Scrollbar( + self.figure_Frame, orient=VERTICAL, cursor="draft_small" + ) self.figure_ybar.pack(side=RIGHT, fill=Y) self.figure_ybar.config(command=self.canvas.yview) - self.figure_xbar = ttk.Scrollbar(self.figure_Frame, orient=HORIZONTAL, cursor='draft_small') + self.figure_xbar = ttk.Scrollbar( + self.figure_Frame, orient=HORIZONTAL, cursor="draft_small" + ) self.figure_xbar.pack(side=BOTTOM, fill=X) self.figure_xbar.config(command=self.canvas.xview) @@ -2968,39 +4156,44 @@ def scoller(): self.show_frame.bind("", onFrameconfigure) def onFrameconfigure(event): - self.canvas.configure(scrollregion=self.canvas.bbox("all"), width=1000, height=650) + self.canvas.configure( + scrollregion=self.canvas.bbox("all"), width=1000, height=650 + ) def choose_color(): colorvalue = colorchooser.askcolor() color_list = [] color = colorvalue[1] print(color) - if 'louvain_colors' in Batch_list[0].uns: - color_lens = [Batch_list[0].uns['louvain_colors'], Batch_list[0].uns['mclust_colors']] + if "louvain_colors" in Batch_list[0].uns: + color_lens = [ + Batch_list[0].uns["louvain_colors"], + Batch_list[0].uns["mclust_colors"], + ] max_len_list = max(color_lens, key=len) max_len = len(max_len_list) - if color[1:3] == 'ff': + if color[1:3] == "ff": color_list.append(color) list = random.sample(color_panel.FF_color, max_len) color_list = color_list + list - elif color[1:3] == 'cc': + elif color[1:3] == "cc": color_list.append(color) list = random.sample(color_panel.CC_color, max_len) color_list = color_list + list - elif color[1:3] == '99': + elif color[1:3] == "99": color_list.append(color) list = random.sample(color_panel.NN_color, max_len) color_list = color_list + list - elif color[1:3] == '66': + elif color[1:3] == "66": color_list.append(color) list = random.sample(color_panel.SS_color, max_len) color_list = color_list + list - elif color[1:3] == '33': + elif color[1:3] == "33": color_list.append(color) list = random.sample(color_panel.TT_color, max_len) color_list = color_list + list - elif color[1:3] == '00': + elif color[1:3] == "00": color_list.append(color) list = random.sample(color_panel.ZZ_color, max_len) color_list = color_list + list @@ -3011,31 +4204,35 @@ def choose_color(): print(color_list) for j in range(len(self.multi_files)): - Batch_list[j].uns['mclust_colors'] = color_list[:len(Batch_list[j].uns['mclust_colors'])] + Batch_list[j].uns["mclust_colors"] = color_list[ + : len(Batch_list[j].uns["mclust_colors"]) + ] - if 'louvain_colors' in Batch_list[0].uns: + if "louvain_colors" in Batch_list[0].uns: for j in range(len(self.multi_files)): - Batch_list[j].uns['louvain_colors'] = color_list[:len(Batch_list[j].uns['louvain_colors'])] + Batch_list[j].uns["louvain_colors"] = color_list[ + : len(Batch_list[j].uns["louvain_colors"]) + ] - adata_new.uns['batch_name_colors'] = color_list[:len(self.multi_files)] + adata_new.uns["batch_name_colors"] = color_list[: len(self.multi_files)] if self.label_files_exit: - adata_new.uns['GroundTruth_colors'] = color_list + adata_new.uns["GroundTruth_colors"] = color_list for section_id in key_add: - adata_list[section_id].uns['GroundTruth_colors'] = color_list + adata_list[section_id].uns["GroundTruth_colors"] = color_list self.color_reset = color_list self.gene_color_type = color_panel.five_gene_color[random.randint(0, 5)] os.chdir(Raw_PATH) draw_images() - fig_path = test_file_path + '/figures/' + self.method_flag + '_output/' + fig_path = test_file_path + "/figures/" + self.method_flag + "_output/" figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 4, column=i % 4, sticky=W, pady=0) - fig_path = test_file_path + '/figures/' + self.method_flag + '_output/' + fig_path = test_file_path + "/figures/" + self.method_flag + "_output/" if not os.path.isdir(fig_path): os.mkdir(fig_path) @@ -3048,40 +4245,59 @@ def choose_color(): self.show_frame = ttk.Frame(self.canvas) scoller() - self.set_frame = ttk.Frame(self.figure_Frame, borderwidth=2, relief="sunken") - self.set_frame.pack(side='right', expand=YES, anchor=N) + self.set_frame = ttk.Frame( + self.figure_Frame, borderwidth=2, relief="sunken" + ) + self.set_frame.pack(side="right", expand=YES, anchor=N) self.set_frame_one = ttk.Frame(self.set_frame) self.set_frame_one.pack(side=TOP, expand=YES) self.set_frame_two = ttk.Frame(self.set_frame) self.set_frame_two.pack(side=TOP, expand=YES) - self.Reset = ttk.Button(self.set_frame_one, text='Reset all colors', command=choose_color, width=12) + self.Reset = ttk.Button( + self.set_frame_one, + text="Reset all colors", + command=choose_color, + width=12, + ) self.Reset.grid(row=0, column=0, sticky=W, pady=0, padx=0) - self.domain_color_label = ttk.Label(self.set_frame_one, text='Reset domain color: ', width=20) + self.domain_color_label = ttk.Label( + self.set_frame_one, text="Reset domain color: ", width=20 + ) self.domain_color_label.grid(row=1, column=0, sticky=W, pady=0) self.Reset_domain_color = ttk.Entry(self.set_frame_one, width=10) self.Reset_domain_color.grid(row=1, column=1, sticky=W, pady=0) - Tooltip(self.Reset_domain_color, "Input value must be int type and in [1:cluster_name]: 2") + Tooltip( + self.Reset_domain_color, + "Input value must be int type and in [1:cluster_name]: 2", + ) self.color_update = None def Reset_single_domain_color(): from tkinter import colorchooser, filedialog + colorvalue = colorchooser.askcolor() color = colorvalue[1] print(color) cluster = self.Reset_domain_color.get() for j in range(len(self.multi_files)): - Batch_list[j].uns['mclust_colors'] = self.color_reset[:len(Batch_list[j].uns['mclust_colors'])] - Batch_list[j].uns['mclust_colors'][int(cluster) - 1] = color + Batch_list[j].uns["mclust_colors"] = self.color_reset[ + : len(Batch_list[j].uns["mclust_colors"]) + ] + Batch_list[j].uns["mclust_colors"][int(cluster) - 1] = color - adata_new.uns['batch_name_colors'] = self.color_reset[:len(self.multi_files)] + adata_new.uns["batch_name_colors"] = self.color_reset[ + : len(self.multi_files) + ] self.color_reset[int(cluster) - 1] = color # self.color_update = self.color_reset - if 'louvain_colors' in Batch_list[0].uns: + if "louvain_colors" in Batch_list[0].uns: for j in range(len(self.multi_files)): - Batch_list[j].uns['louvain_colors'] = self.color_reset[:len(Batch_list[j].uns['louvain_colors'])] + Batch_list[j].uns["louvain_colors"] = self.color_reset[ + : len(Batch_list[j].uns["louvain_colors"]) + ] draw_images() # import matplotlib.pyplot as plt @@ -3128,36 +4344,51 @@ def Reset_single_domain_color(): global image_list image_list = [] for i in range(len(figures)): - img = Image.open(fig_path + '/' + figures[i]) + img = Image.open(fig_path + "/" + figures[i]) print(img.size) - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) - self.result_images.grid(row=i // 4, column=i % 4, sticky=W, pady=0, padx=0) + self.result_images.grid( + row=i // 4, column=i % 4, sticky=W, pady=0, padx=0 + ) s = i - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Confirm', - command=Reset_single_domain_color) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, + width=10, + text="Confirm", + command=Reset_single_domain_color, + ) self.Reset_domain_btn.grid(row=1, column=2, sticky=W, pady=10) - self.update_image_label = ttk.Label(self.set_frame_one, text='Reset image dpi: ', width=20) + self.update_image_label = ttk.Label( + self.set_frame_one, text="Reset image dpi: ", width=20 + ) self.update_image_label.grid(row=2, column=0, sticky=W, pady=10) self.update_image_scale = ttk.Entry(self.set_frame_one, width=10) self.update_image_scale.grid(row=2, column=1, sticky=W, pady=10) - Tooltip(self.update_image_scale, "Input value must be int type and >= 300: 300") + Tooltip( + self.update_image_scale, "Input value must be int type and >= 300: 300" + ) def ipdate_hd(): dpi = self.update_image_scale.get() print(dpi) import matplotlib.pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) sc.set_figure_params(dpi=dpi) draw_images() figures = os.listdir(fig_path) print(len(figures)) - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Save', command=ipdate_hd) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, width=10, text="Save", command=ipdate_hd + ) self.Reset_domain_btn.grid(row=2, column=2, sticky=W, pady=0) - self.gene_visualization_label = ttk.Label(self.set_frame_one, text='Input gene name: ', width=20) + self.gene_visualization_label = ttk.Label( + self.set_frame_one, text="Input gene name: ", width=20 + ) self.gene_visualization_label.grid(row=3, column=0, sticky=W, pady=0) self.gene_visualization_entry = ttk.Entry(self.set_frame_one, width=10) @@ -3170,32 +4401,43 @@ def gene_visualization(): print(adata_list[self.multi_files[-1]].var.index) if gene in adata_list[self.multi_files[-1]].var_names: - sc.pl.spatial(adata_list[self.multi_files[-1]], img_key="hires", color=gene, title="$" + gene + "$", - show=False, save=gene + '.png', sopt_size=150) + sc.pl.spatial( + adata_list[self.multi_files[-1]], + img_key="hires", + color=gene, + title="$" + gene + "$", + show=False, + save=gene + ".png", + sopt_size=150, + ) else: - print(f'{gene} is not in adata!') + print(f"{gene} is not in adata!") global img0 - photo = Image.open(test_file_path + '/figures/show' + gene + '.png') + photo = Image.open(test_file_path + "/figures/show" + gene + ".png") img0 = ImageTk.PhotoImage(photo) img1 = ttk.Label(self.set_frame_two, image=img0) img1.grid(row=0, column=0, sticky=W, pady=0) - if os.path.exists(test_file_path + '/figures/show' + gene + '.png'): - os.remove(test_file_path + '/figures/show' + gene + '.png') + if os.path.exists(test_file_path + "/figures/show" + gene + ".png"): + os.remove(test_file_path + "/figures/show" + gene + ".png") print("Figures exits") else: print("Figures no exits!") pass except: - Messagebox.show_error("Python Error", "Make sure gene name in dataset") + Messagebox.show_error( + "Python Error", "Make sure gene name in dataset" + ) - self.gene_visualization_btn = ttk.Button(self.set_frame_one, width=10, command=gene_visualization, text='Show') + self.gene_visualization_btn = ttk.Button( + self.set_frame_one, width=10, command=gene_visualization, text="Show" + ) self.gene_visualization_btn.grid(row=3, column=2, sticky=W, pady=0) global image_list image_list = [] s = 0 for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 4, column=i % 4, sticky=W, pady=0) s = i @@ -3206,81 +4448,106 @@ def gene_visualization(): def VIEW_3D(): import webbrowser + self.web_Server_Thread("/STAligner_3D/webcache", int(self.Entry.get())) - http = 'http://127.0.0.1:' + self.Entry.get() + '/' + http = "http://127.0.0.1:" + self.Entry.get() + "/" # 'http://127.0.0.1:8050/' webbrowser.open(http) - self.Reset = ttk.Button(self.set_frame_one, text='3D VIEW', command=VIEW_3D, width=10) + self.Reset = ttk.Button( + self.set_frame_one, text="3D VIEW", command=VIEW_3D, width=10 + ) self.Reset.grid(row=0, column=2, sticky=W, pady=0) else: - Messagebox.show_warning(title="Attention", message='Waiting for models training!!!') + Messagebox.show_warning( + title="Attention", message="Waiting for models training!!!" + ) def STAligner_Multiple_Sections_analysis(self): self.Dataload() self.model_train_flag = False self.cluster_flag = False - for i in range(self.result_queue.qsize()-1): + for i in range(self.result_queue.qsize() - 1): adata_remove = self.result_queue.get() del adata_remove adata_new = self.result_queue.get() - if 'GroundTruth' in adata_new.obs.columns or 'GroundTruth_colors' in adata_new.uns.columns: + if ( + "GroundTruth" in adata_new.obs.columns + or "GroundTruth_colors" in adata_new.uns.columns + ): self.label_files_exit = True adata_list = {} key_add = [] for section_id in self.multi_files: - file_name = section_id.rsplit('\\', 1)[-1] - k = file_name.rsplit('.', 1)[-2] + file_name = section_id.rsplit("\\", 1)[-1] + k = file_name.rsplit(".", 1)[-2] key_add.append(k) temp_adata = sc.read(section_id) temp_adata.var_names_make_unique() - temp_adata.obs_names = [x + '_' + k for x in temp_adata.obs_names] + temp_adata.obs_names = [x + "_" + k for x in temp_adata.obs_names] adata_list[k] = temp_adata.copy() # self.result_queue.put(adata_list) # adata_list.write_h5ad(os.path.join(running_path, "result", "STAligner_GroundTruth_output.h5ad")) # del temp_adata, adata_list - if 'STAligner' not in adata_new.obsm: - staligner = STAligner(model_dir=running_path + "/result/", - in_features=3000, hidden_dims=[512, 30], - n_models=5, device=torch.device("cuda:0")) - adata_new = staligner.train(adata_new, iter_comb=[(0, 1)], n_epochs=int(self.cluster_value), - lr=float(self.alpha_value), margin=float(self.adjust_value)) - sc.pp.neighbors(adata_new, use_rep='STAligner', random_state=666) + if "STAligner" not in adata_new.obsm: + staligner = STAligner( + model_dir=running_path + "/result/", + in_features=3000, + hidden_dims=[512, 30], + n_models=5, + device=torch.device("cuda:0"), + ) + adata_new = staligner.train( + adata_new, + iter_comb=[(0, 1)], + n_epochs=int(self.cluster_value), + lr=float(self.alpha_value), + margin=float(self.adjust_value), + ) + sc.pp.neighbors(adata_new, use_rep="STAligner", random_state=666) sc.tl.umap(adata_new, random_state=666) - data_save_path = test_file_path + '/STAligner_3D' + data_save_path = test_file_path + "/STAligner_3D" if not os.path.exists(data_save_path): os.makedirs(data_save_path) - del adata_new.uns['edgeList'] - adata_new.write_h5ad(os.path.join(data_save_path, 'STAligner_Multi_DLPFC.h5ad')) + del adata_new.uns["edgeList"] + adata_new.write_h5ad( + os.path.join(data_save_path, "STAligner_Multi_DLPFC.h5ad") + ) json_file = { "Coordinate": "spatial", "Annotatinos": ["mclust"], - "Meshes": { - }, + "Meshes": {}, "mesh_coord": "fixed.json", - "Genes": [ - "all" - ] + "Genes": ["all"], } fixed_file = {"xmin": 0, "ymin": 0, "margin": 0, "zmin": 0, "binsize": 1} - json.dump(json_file, open(os.path.join(data_save_path, 'Multi-DLPFC.json'), 'w'), indent=4) - json.dump(fixed_file, open(os.path.join(data_save_path, 'fixed.json'), 'w')) - self.web_Thread(data_save_path, 'STAligner_Multi_DLPFC.h5ad', 'Multi-DLPFC.json', 'Multi-DLPFC') + json.dump( + json_file, + open(os.path.join(data_save_path, "Multi-DLPFC.json"), "w"), + indent=4, + ) + json.dump(fixed_file, open(os.path.join(data_save_path, "fixed.json"), "w")) + self.web_Thread( + data_save_path, + "STAligner_Multi_DLPFC.h5ad", + "Multi-DLPFC.json", + "Multi-DLPFC", + ) # self.result_queue.put(adata_new) data_path = os.path.join(running_path, "result", "STAligner_output.h5ad") print(adata_new) - del adata_new.uns['edgeList'] + del adata_new.uns["edgeList"] print(f"Training file is saved in {data_path} ") adata_new.write_h5ad(data_path) self.pb.stop() - self.pb['value'] = 100 - self.setvar('prog-message', 'STAligner run over!') - self.setvar('End-time', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + self.pb["value"] = 100 + self.setvar("prog-message", "STAligner run over!") + self.setvar("End-time", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) EndTime = datetime.now().replace(microsecond=0) - self.setvar('total-time-cost', EndTime - self.StartTime) + self.setvar("total-time-cost", EndTime - self.StartTime) self.model_train_flag = True self.cluster_flag = True @@ -3293,10 +4560,21 @@ def STAMarker_show(self): if self.cluster_flag: self.result_flag = True # print(f"self.result_queue长度:{self.result_queue.qsize()}!!!") - self.gene_color_type = 'viridis' + self.gene_color_type = "viridis" ann_data = self.result_queue.get() - data_path = test_file_path + "/STAMarker_ouput/" + self.method_flag + '_' + self.data_type + '_output' - df = pd.read_csv(os.path.join(running_path, "result", "STAMarker_find_SVGs.txt"), sep="\t", index_col=False) + data_path = ( + test_file_path + + "/STAMarker_ouput/" + + self.method_flag + + "_" + + self.data_type + + "_output" + ) + df = pd.read_csv( + os.path.join(running_path, "result", "STAMarker_find_SVGs.txt"), + sep="\t", + index_col=False, + ) genes_list = df.values.tolist() # print(f"now self.result_queue长度:{self.result_queue.qsize()}!!!") @@ -3305,44 +4583,89 @@ def draw_images(): temp_path = os.getcwd() os.chdir(test_file_path) from matplotlib import pyplot as plt - plt.rcParams['font.sans-serif'] = "Arial" + + plt.rcParams["font.sans-serif"] = "Arial" plt.rcParams["figure.figsize"] = (3, 3) - path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + ) if self.label_files_exit: - sc.pl.spatial(ann_data, img_key="hires", color="GroundTruth", title="Ground Truth", s=6, show=False, - save='STAMarker_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAMarker_' + str(i) + '.png', - path + '/STAMarker_' + str(i) + '.png') + sc.pl.spatial( + ann_data, + img_key="hires", + color="GroundTruth", + title="Ground Truth", + s=6, + show=False, + save="STAMarker_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAMarker_" + str(i) + ".png", + path + "/STAMarker_" + str(i) + ".png", + ) i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.spatial(ann_data, img_key="hires", color="Consensus_clustering", title="STAMarker", s=6, - show=False, spot_size=self.spot_size, save='STAMarker_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSTAMarker_' + str(i) + '.png', - path + '/STAMarker_' + str(i) + '.png') + sc.pl.spatial( + ann_data, + img_key="hires", + color="Consensus_clustering", + title="STAMarker", + s=6, + show=False, + spot_size=self.spot_size, + save="STAMarker_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSTAMarker_" + str(i) + ".png", + path + "/STAMarker_" + str(i) + ".png", + ) - genes = genes_list[:self.show_gene_num] + genes = genes_list[: self.show_gene_num] if self.show_gene_name in genes_list: genes = genes.append(self.show_gene_name) plt.rcParams["figure.figsize"] = (3, 3) j = 0 i = i + 1 for k in genes: - sc.pl.spatial(ann_data, img_key="hires", color=k, title=k, s=6, show=False, spot_size=self.spot_size, - color_map=self.gene_color_type, save='STAMarker_' + str(i) + "_" + str(j) + '.png') - shutil.move(test_file_path + '/figures/showSTAMarker_' + str(i) + "_" + str(j) + '.png', - path + '/STAMarker_' + - str(i) + "_" + str(j) + '.png') + sc.pl.spatial( + ann_data, + img_key="hires", + color=k, + title=k, + s=6, + show=False, + spot_size=self.spot_size, + color_map=self.gene_color_type, + save="STAMarker_" + str(i) + "_" + str(j) + ".png", + ) + shutil.move( + test_file_path + + "/figures/showSTAMarker_" + + str(i) + + "_" + + str(j) + + ".png", + path + "/STAMarker_" + str(i) + "_" + str(j) + ".png", + ) j = j + 1 - print(f'Result images are saved in : {test_file_path}/figures') + print(f"Result images are saved in : {test_file_path}/figures") os.chdir(temp_path) def scoller(): - self.figure_ybar = ttk.Scrollbar(self.figure_Frame, orient=VERTICAL, cursor='draft_small') + self.figure_ybar = ttk.Scrollbar( + self.figure_Frame, orient=VERTICAL, cursor="draft_small" + ) self.figure_ybar.pack(side=RIGHT, fill=Y) self.figure_ybar.config(command=self.canvas.yview) - self.figure_xbar = ttk.Scrollbar(self.figure_Frame, orient=HORIZONTAL, cursor='draft_small') + self.figure_xbar = ttk.Scrollbar( + self.figure_Frame, orient=HORIZONTAL, cursor="draft_small" + ) self.figure_xbar.pack(side=BOTTOM, fill=X) self.figure_xbar.config(command=self.canvas.xview) @@ -3356,7 +4679,9 @@ def scoller(): self.show_frame.bind("", onFrameconfigure) def onFrameconfigure(event): - self.canvas.configure(scrollregion=self.canvas.bbox("all"), width=1000, height=650) + self.canvas.configure( + scrollregion=self.canvas.bbox("all"), width=1000, height=650 + ) def choose_color(): colorvalue = colorchooser.askcolor() @@ -3364,27 +4689,27 @@ def choose_color(): color = colorvalue[1] # if len(ann_data.uns['Consensus_clustering_colors']) > self.cluster_value: # self.cluster_value = len(ann_data.uns['Consensus_clustering_colors']) - if color[1:3] == 'ff': + if color[1:3] == "ff": color_list.append(color) list = random.sample(color_panel.FF_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == 'cc': + elif color[1:3] == "cc": color_list.append(color) list = random.sample(color_panel.CC_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '99': + elif color[1:3] == "99": color_list.append(color) list = random.sample(color_panel.NN_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '66': + elif color[1:3] == "66": color_list.append(color) list = random.sample(color_panel.SS_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '33': + elif color[1:3] == "33": color_list.append(color) list = random.sample(color_panel.TT_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '00': + elif color[1:3] == "00": color_list.append(color) list = random.sample(color_panel.ZZ_color, self.cluster_value) color_list = color_list + list @@ -3395,39 +4720,54 @@ def choose_color(): print(color_list) if self.label_files_exit: - ann_data.uns['GroundTruth_colors'] = color_list[:len(ann_data.uns['GroundTruth_colors'])] + ann_data.uns["GroundTruth_colors"] = color_list[ + : len(ann_data.uns["GroundTruth_colors"]) + ] # ann_data.uns['Consensus_clustering_colors'] = color_list[ # :len(ann_data.uns['Consensus_clustering_colors'])] self.gene_color_type = color_panel.five_gene_color[random.randint(0, 5)] self.color_reset = color_list draw_images() - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type # './figures/showSTAMarker_10XVisium' + fig_path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + ) # './figures/showSTAMarker_10XVisium' figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0) if self.data_type is None: - self.data_type = '10x' - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + self.data_type = "10x" + fig_path = ( + test_file_path + "/figures/" + self.method_flag + "_" + self.data_type + ) if not os.path.isdir(fig_path): os.mkdir(fig_path) - images_path = glob.glob(data_path + '/*.png') + images_path = glob.glob(data_path + "/*.png") num = 4 ll = 0 for i in images_path: plt.Figure(figsize=(3, 3)) image = plt.imread(i) plt.imshow(image) - plt.axis('off') + plt.axis("off") plt.savefig(i) plt.close() - shutil.move(i, os.path.join(fig_path, "STAMarker_GSEA_" + str(num) + '_' + str(ll) + '.png')) + shutil.move( + i, + os.path.join( + fig_path, "STAMarker_GSEA_" + str(num) + "_" + str(ll) + ".png" + ), + ) ll = ll + 1 pass draw_images() @@ -3438,26 +4778,39 @@ def choose_color(): self.show_frame = ttk.Frame(self.canvas) scoller() - self.set_frame = ttk.Frame(self.figure_Frame, borderwidth=2, relief="sunken") - self.set_frame.pack(side='right', expand=YES, anchor=N) + self.set_frame = ttk.Frame( + self.figure_Frame, borderwidth=2, relief="sunken" + ) + self.set_frame.pack(side="right", expand=YES, anchor=N) self.set_frame_one = ttk.Frame(self.set_frame) self.set_frame_one.pack(side=TOP, expand=YES) self.set_frame_two = ttk.Frame(self.set_frame) self.set_frame_two.pack(side=TOP, expand=YES) - self.Reset = ttk.Button(self.set_frame_one, text='Reset all colors', command=choose_color, width=12) + self.Reset = ttk.Button( + self.set_frame_one, + text="Reset all colors", + command=choose_color, + width=12, + ) self.Reset.grid(row=0, column=0, sticky=W, pady=0, padx=0) - self.domain_color_label = ttk.Label(self.set_frame_one, text='Reset domain color: ', width=20) + self.domain_color_label = ttk.Label( + self.set_frame_one, text="Reset domain color: ", width=20 + ) self.domain_color_label.grid(row=1, column=0, sticky=W, pady=0) self.Reset_domain_color = ttk.Entry(self.set_frame_one, width=10) self.Reset_domain_color.grid(row=1, column=1, sticky=W, pady=0) - Tooltip(self.Reset_domain_color, "Input value must be int type and in [1:cluster_name]: 2") + Tooltip( + self.Reset_domain_color, + "Input value must be int type and in [1:cluster_name]: 2", + ) self.color_update = None def Reset_single_domain_color(): from tkinter import colorchooser, filedialog + colorvalue = colorchooser.askcolor() color = colorvalue[1] print(color) @@ -3467,6 +4820,7 @@ def Reset_single_domain_color(): # ann_data.uns['Consensus_clustering_colors'] = self.color_reset[:len(ann_data.uns['Consensus_clustering_colors'])] # # self.color_update = ann_data.uns['mclust_colors'] import matplotlib.pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) draw_images() @@ -3474,21 +4828,31 @@ def Reset_single_domain_color(): global image_list image_list = [] for i in range(len(figures)): - img = Image.open(fig_path + '/' + figures[i]) + img = Image.open(fig_path + "/" + figures[i]) print(img.size) - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) - self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0, padx=0) + self.result_images.grid( + row=i // 3, column=i % 3, sticky=W, pady=0, padx=0 + ) s = i - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Confirm', - command=Reset_single_domain_color) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, + width=10, + text="Confirm", + command=Reset_single_domain_color, + ) self.Reset_domain_btn.grid(row=1, column=2, sticky=W, pady=10) - self.update_image_label = ttk.Label(self.set_frame_one, text='Reset image dpi: ', width=20) + self.update_image_label = ttk.Label( + self.set_frame_one, text="Reset image dpi: ", width=20 + ) self.update_image_label.grid(row=2, column=0, sticky=W, pady=10) self.update_image_scale = ttk.Entry(self.set_frame_one, width=10) self.update_image_scale.grid(row=2, column=1, sticky=W, pady=10) - Tooltip(self.update_image_scale, "Input value must be int type and >= 300: 300") + Tooltip( + self.update_image_scale, "Input value must be int type and >= 300: 300" + ) def ipdate_hd(): dpi = self.update_image_scale.get() @@ -3496,14 +4860,19 @@ def ipdate_hd(): print(self.color_update) # ann_data.uns['Consensus_clustering_colors'] = self.color_update import matplotlib.pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) sc.set_figure_params(dpi=dpi) draw_images() - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Save', command=ipdate_hd) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, width=10, text="Save", command=ipdate_hd + ) self.Reset_domain_btn.grid(row=2, column=2, sticky=W, pady=0) - self.gene_visualization_label = ttk.Label(self.set_frame_one, text='Input gene name: ', width=20) + self.gene_visualization_label = ttk.Label( + self.set_frame_one, text="Input gene name: ", width=20 + ) self.gene_visualization_label.grid(row=3, column=0, sticky=W, pady=0) self.gene_visualization_entry = ttk.Entry(self.set_frame_one, width=10) @@ -3513,43 +4882,56 @@ def ipdate_hd(): def gene_visualization(): gene = self.gene_visualization_entry.get() if gene in ann_data.var_names: - sc.pl.spatial(ann_data, img_key="hires", color=gene, title="$" + gene + "$", show=False, - save=gene + '.png') + sc.pl.spatial( + ann_data, + img_key="hires", + color=gene, + title="$" + gene + "$", + show=False, + save=gene + ".png", + ) else: - print(f'{gene} is not in current data!') + print(f"{gene} is not in current data!") global img0 - photo = Image.open(test_file_path + '/figures/show' + gene + '.png') + photo = Image.open(test_file_path + "/figures/show" + gene + ".png") img0 = ImageTk.PhotoImage(photo) img1 = ttk.Label(self.set_frame_two, image=img0) img1.grid(row=0, column=0, sticky=W, pady=0) - if os.path.exists(test_file_path + '/figures/show' + gene + '.png'): - os.remove(test_file_path + '/figures/show' + gene + '.png') + if os.path.exists(test_file_path + "/figures/show" + gene + ".png"): + os.remove(test_file_path + "/figures/show" + gene + ".png") print("yes") else: print("error!") - self.gene_visualization_btn = ttk.Button(self.set_frame_one, width=10, command=gene_visualization, text='Show') + self.gene_visualization_btn = ttk.Button( + self.set_frame_one, width=10, command=gene_visualization, text="Show" + ) self.gene_visualization_btn.grid(row=3, column=2, sticky=W, pady=0) figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0) s = i def VIEW_3D(): import webbrowser - self.web_Server_Thread(os.path.join('/DLPFC/webcache'), 8050) - webbrowser.open('http://127.0.0.1:8050/') - self.Reset = ttk.Button(self.set_frame_one, text='3D VIEW', command=VIEW_3D, width=10) + self.web_Server_Thread(os.path.join("/DLPFC/webcache"), 8050) + webbrowser.open("http://127.0.0.1:8050/") + + self.Reset = ttk.Button( + self.set_frame_one, text="3D VIEW", command=VIEW_3D, width=10 + ) self.Reset.grid(row=0, column=1, sticky=W, pady=0) self.result_queue.put(ann_data) else: - Messagebox.show_warning(title="Attention", message='Waiting for models training!!!') + Messagebox.show_warning( + title="Attention", message="Waiting for models training!!!" + ) def STAMarker_Data_Analysis(self): model_dir = test_file_path + "/STAMarker_ouput/" @@ -3562,74 +4944,122 @@ def STAMarker_Data_Analysis(self): del adata_remove if not self.result_queue.empty(): ann_data = self.result_queue.get() - if 'GroundTruth' in ann_data.obs.columns: + if "GroundTruth" in ann_data.obs.columns: self.label_files_exit = True - if 'highly_variable' in ann_data.var.columns: - ann_data = ann_data[:, ann_data.var['highly_variable']] + if "highly_variable" in ann_data.var.columns: + ann_data = ann_data[:, ann_data.var["highly_variable"]] else: - sc.pp.highly_variable_genes(ann_data, flavor="seurat_v3", n_top_genes=3000) - ann_data = ann_data[:, ann_data.var['highly_variable']] + sc.pp.highly_variable_genes( + ann_data, flavor="seurat_v3", n_top_genes=3000 + ) + ann_data = ann_data[:, ann_data.var["highly_variable"]] Cal_Spatial_Net(ann_data, int(self.rad_cutoff_value)) Stats_Spatial_Net(ann_data) - stamarker = STAMarker(model_dir=model_dir, in_features=ann_data.shape[1], hidden_dims=[512, 30], - n_models=int(self.alpha_value), device=torch.device("cuda:0")) - stamarker.train(ann_data, lr=1e-4, n_epochs=int(self.train_epoch_num), gradient_clip=5.0, use_net="Spatial_Net", - resume=False, plot_consensus=True, clf_n_epochs=int(self.cla_epoch_num), n_clusters=int(self.cluster_value)) + stamarker = STAMarker( + model_dir=model_dir, + in_features=ann_data.shape[1], + hidden_dims=[512, 30], + n_models=int(self.alpha_value), + device=torch.device("cuda:0"), + ) + stamarker.train( + ann_data, + lr=1e-4, + n_epochs=int(self.train_epoch_num), + gradient_clip=5.0, + use_net="Spatial_Net", + resume=False, + plot_consensus=True, + clf_n_epochs=int(self.cla_epoch_num), + n_clusters=int(self.cluster_value), + ) stamarker.predict(ann_data, use_net="Spatial_Net") - output = stamarker.select_spatially_variable_genes(ann_data, use_smap="smap", alpha=1.5) - ann_data.obs['Consensus_clustering'] = ann_data.uns['STAMarker']["consensus_labels"].astype(str) - genes_list = output['gene_list'] + output = stamarker.select_spatially_variable_genes( + ann_data, use_smap="smap", alpha=1.5 + ) + ann_data.obs["Consensus_clustering"] = ann_data.uns["STAMarker"][ + "consensus_labels" + ].astype(str) + genes_list = output["gene_list"] df = pd.DataFrame(genes_list) - df.to_csv(os.path.join(running_path, "result", "STAMarker_find_SVGs.txt"), sep="\t", index=False, header=False) + df.to_csv( + os.path.join(running_path, "result", "STAMarker_find_SVGs.txt"), + sep="\t", + index=False, + header=False, + ) if self.data_type is None: self.data_type = "10x" - data_path = test_file_path + "/STAMarker_ouput/" + self.method_flag + '_' + self.data_type + '_output' + data_path = ( + test_file_path + + "/STAMarker_ouput/" + + self.method_flag + + "_" + + self.data_type + + "_output" + ) if not os.path.isdir(data_path): os.mkdir(data_path) num = 1 - enr = gp.enrichr(gene_list=genes_list, # or "./tests/data/gene_list.txt", - gene_sets=['GO_Biological_Process_2018', 'KEGG_2019'], - organism='human', - outdir=None, - ) - - ax = dotplot(enr.results, - column="Adjusted P-value", - x='Gene_set', - size=10, - top_term=5, - figsize=(3, 3), - title="Enrich", - xticklabels_rot=45, - show_ring=True, - ofname=os.path.join(data_path, "STAMarker_SVGs_" + str(num) + ".png"), - marker='o', - ) + enr = gp.enrichr( + gene_list=genes_list, # or "./tests/data/gene_list.txt", + gene_sets=["GO_Biological_Process_2018", "KEGG_2019"], + organism="human", + outdir=None, + ) + + ax = dotplot( + enr.results, + column="Adjusted P-value", + x="Gene_set", + size=10, + top_term=5, + figsize=(3, 3), + title="Enrich", + xticklabels_rot=45, + show_ring=True, + ofname=os.path.join(data_path, "STAMarker_SVGs_" + str(num) + ".png"), + marker="o", + ) num = num + 1 - ax = barplot(enr.results, - column="Adjusted P-value", - group='Gene_set', - size=10, - top_term=5, - figsize=(3, 3), - ofname=os.path.join(data_path, "STAMarker_SVGs_" + str(num) + ".png"), - color=['darkred', 'darkblue'] - ) + ax = barplot( + enr.results, + column="Adjusted P-value", + group="Gene_set", + size=10, + top_term=5, + figsize=(3, 3), + ofname=os.path.join(data_path, "STAMarker_SVGs_" + str(num) + ".png"), + color=["darkred", "darkblue"], + ) num = num + 1 - ax = dotplot(enr.res2d, title='KEGG_2021', cmap='viridis_r', size=10, figsize=(3, 3), - ofname=os.path.join(data_path, "STAMarker_SVGs_" + str(num) + ".png")) + ax = dotplot( + enr.res2d, + title="KEGG_2021", + cmap="viridis_r", + size=10, + figsize=(3, 3), + ofname=os.path.join(data_path, "STAMarker_SVGs_" + str(num) + ".png"), + ) num = num + 1 - ax = barplot(enr.res2d, title='KEGG_2021', figsize=(3, 3), color='darkred', - ofname=os.path.join(data_path, "STAMarker_SVGs_" + str(num) + ".png")) + ax = barplot( + enr.res2d, + title="KEGG_2021", + figsize=(3, 3), + color="darkred", + ofname=os.path.join(data_path, "STAMarker_SVGs_" + str(num) + ".png"), + ) # self.result_queue.put(ann_data) - ann_data.write_h5ad(os.path.join(running_path, "result", "STAMarker_output.h5ad")) + ann_data.write_h5ad( + os.path.join(running_path, "result", "STAMarker_output.h5ad") + ) self.pb.stop() - self.pb['value'] = 100 - self.setvar('prog-message', 'STAMarker run over!') - self.setvar('End-time', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + self.pb["value"] = 100 + self.setvar("prog-message", "STAMarker run over!") + self.setvar("End-time", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) EndTime = datetime.now().replace(microsecond=0) - self.setvar('total-time-cost', EndTime - self.StartTime) + self.setvar("total-time-cost", EndTime - self.StartTime) self.model_train_flag = True self.cluster_flag = True @@ -3657,89 +5087,203 @@ def draw_images(): i = 1 j = 1 from matplotlib import pyplot as plt + os.chdir(Raw_PATH) - plt.rcParams['font.sans-serif'] = "Arial" + plt.rcParams["font.sans-serif"] = "Arial" plt.rcParams["figure.figsize"] = (3, 3) - path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + '/' + path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + + "/" + ) if self.label_files_exit: - sc.pl.spatial(adata, img_key="hires", color="layer", title='Ground Truth', show=False, - save='STAGE_' + str(i) + '.png', spot_size=self.spot_size) - shutil.move(test_file_path + '/figures/showSTAGE_' + str(i) + '.png', path + 'STAGE_' + str(j) + '_' + str(i) + '.png') + sc.pl.spatial( + adata, + img_key="hires", + color="layer", + title="Ground Truth", + show=False, + save="STAGE_" + str(i) + ".png", + spot_size=self.spot_size, + ) + shutil.move( + test_file_path + "/figures/showSTAGE_" + str(i) + ".png", + path + "STAGE_" + str(j) + "_" + str(i) + ".png", + ) - adata.obsm['coord'][:, 1] = adata.obsm['coord'][:, 1] * (-1) + adata.obsm["coord"][:, 1] = adata.obsm["coord"][:, 1] * (-1) i = i + 1 - used_adata = adata[adata.obs['layer'].isna() == False,] + used_adata = adata[adata.obs["layer"].isna() == False,] plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(used_adata, color='layer', title='Original', show=False, s=6, - save='STAGE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGE_' + str(i) + '.png', path + 'STAGE_' + str(j) + '_' + str(i) + '.png') + sc.pl.umap( + used_adata, + color="layer", + title="Original", + show=False, + s=6, + save="STAGE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGE_" + str(i) + ".png", + path + "STAGE_" + str(j) + "_" + str(i) + ".png", + ) i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.tl.paga(used_adata, groups='layer') - sc.pl.paga(used_adata, color="layer", title='Original-PAGA', show=False, - save='STAGE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/pagaSTAGE_' + str(i) + '.png', path + 'STAGE_' + str(j) + '_' + str(i) + '.png') + sc.tl.paga(used_adata, groups="layer") + sc.pl.paga( + used_adata, + color="layer", + title="Original-PAGA", + show=False, + save="STAGE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/pagaSTAGE_" + str(i) + ".png", + path + "STAGE_" + str(j) + "_" + str(i) + ".png", + ) i = i + 1 - used_adata_sample = adata_sample[adata_sample.obs['layer'].isna() == False,] + used_adata_sample = adata_sample[ + adata_sample.obs["layer"].isna() == False, + ] plt.rcParams["figure.figsize"] = (3, 3) - used_adata_sample.uns['layer_colors'] = used_adata.uns['layer_colors'] - sc.pl.umap(used_adata_sample, color='layer', title='Down-Sampling', show=False, - save='STAGE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGE_' + str(i) + '.png', path + 'STAGE_' + str(j) + '_' + str(i) + '.png') + used_adata_sample.uns["layer_colors"] = used_adata.uns[ + "layer_colors" + ] + sc.pl.umap( + used_adata_sample, + color="layer", + title="Down-Sampling", + show=False, + save="STAGE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGE_" + str(i) + ".png", + path + "STAGE_" + str(j) + "_" + str(i) + ".png", + ) i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.tl.paga(used_adata_sample, groups='layer') - sc.pl.paga(used_adata_sample, color="layer", title='Down-Sampling-PAGA', show=False, - save='STAGE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/pagaSTAGE_' + str(i) + '.png', path + 'STAGE_' + str(j) + '_' + str(i) + '.png') + sc.tl.paga(used_adata_sample, groups="layer") + sc.pl.paga( + used_adata_sample, + color="layer", + title="Down-Sampling-PAGA", + show=False, + save="STAGE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/pagaSTAGE_" + str(i) + ".png", + path + "STAGE_" + str(j) + "_" + str(i) + ".png", + ) i = i + 1 - used_adata_stage = adata_stage[adata_stage.obs['layer'].isna() == False,] + used_adata_stage = adata_stage[ + adata_stage.obs["layer"].isna() == False, + ] plt.rcParams["figure.figsize"] = (3, 3) - used_adata_stage.uns['layer_colors'] = used_adata.uns['layer_colors'] - sc.pl.umap(used_adata_stage, color='layer', title='Recoverd', show=False, - save='STAGE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSTAGE_' + str(i) + '.png', path + 'STAGE_' + str(j) + '_' + str(i) + '.png') + used_adata_stage.uns["layer_colors"] = used_adata.uns[ + "layer_colors" + ] + sc.pl.umap( + used_adata_stage, + color="layer", + title="Recoverd", + show=False, + save="STAGE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSTAGE_" + str(i) + ".png", + path + "STAGE_" + str(j) + "_" + str(i) + ".png", + ) i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.tl.paga(used_adata_stage, groups='layer') - sc.pl.paga(used_adata_stage, color="layer", title='Recoverd-PAGA', show=False, - save='STAGE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/pagaSTAGE_' + str(i) + '.png', path + 'STAGE_' + str(j) + '_' + str(i) + '.png') + sc.tl.paga(used_adata_stage, groups="layer") + sc.pl.paga( + used_adata_stage, + color="layer", + title="Recoverd-PAGA", + show=False, + save="STAGE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/pagaSTAGE_" + str(i) + ".png", + path + "STAGE_" + str(j) + "_" + str(i) + ".png", + ) j = j + 1 i = 1 if self.show_gene_name not in common_gene_names: self.show_gene_name = common_gene_names_list[0] plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.embedding(adata, basis="coord", color=self.show_gene_name, title=self.show_gene_name, s=6, show=False, - color_map=self.gene_color_type, save='STAGE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/coordSTAGE_' + str(i) + '.png', path + 'STAGE_' + str(j) + '_' + str(i) + '.png') + sc.pl.embedding( + adata, + basis="coord", + color=self.show_gene_name, + title=self.show_gene_name, + s=6, + show=False, + color_map=self.gene_color_type, + save="STAGE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/coordSTAGE_" + str(i) + ".png", + path + "STAGE_" + str(j) + "_" + str(i) + ".png", + ) i = i + 1 - adata_sample.obsm['coord'][:, 1] = adata_sample.obsm['coord'][:, 1] * (-1) + adata_sample.obsm["coord"][:, 1] = adata_sample.obsm["coord"][:, 1] * ( + -1 + ) plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.embedding(adata_sample, basis="coord", color=self.show_gene_name, title=self.show_gene_name, s=6, show=False, - color_map=self.gene_color_type, save='STAGE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/coordSTAGE_' + str(i) + '.png', path + 'STAGE_' + str(j) + '_' + str(i) + '.png') + sc.pl.embedding( + adata_sample, + basis="coord", + color=self.show_gene_name, + title=self.show_gene_name, + s=6, + show=False, + color_map=self.gene_color_type, + save="STAGE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/coordSTAGE_" + str(i) + ".png", + path + "STAGE_" + str(j) + "_" + str(i) + ".png", + ) i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.embedding(adata_stage, basis="coord", color=self.show_gene_name, title=self.show_gene_name, s=6, show=False, - color_map=self.gene_color_type, save='STAGE_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/coordSTAGE_' + str(i) + '.png', path + 'STAGE_' + str(j) + '_' + str(i) + '.png') - print(f'Result images are saved in : {test_file_path}/figures') + sc.pl.embedding( + adata_stage, + basis="coord", + color=self.show_gene_name, + title=self.show_gene_name, + s=6, + show=False, + color_map=self.gene_color_type, + save="STAGE_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/coordSTAGE_" + str(i) + ".png", + path + "STAGE_" + str(j) + "_" + str(i) + ".png", + ) + print(f"Result images are saved in : {test_file_path}/figures") def scoller(): - self.figure_ybar = ttk.Scrollbar(self.figure_Frame, orient=VERTICAL, cursor='draft_small') + self.figure_ybar = ttk.Scrollbar( + self.figure_Frame, orient=VERTICAL, cursor="draft_small" + ) self.figure_ybar.pack(side=RIGHT, fill=Y) self.figure_ybar.config(command=self.canvas.yview) - self.figure_xbar = ttk.Scrollbar(self.figure_Frame, orient=HORIZONTAL, cursor='draft_small') + self.figure_xbar = ttk.Scrollbar( + self.figure_Frame, orient=HORIZONTAL, cursor="draft_small" + ) self.figure_xbar.pack(side=BOTTOM, fill=X) self.figure_xbar.config(command=self.canvas.xview) @@ -3753,26 +5297,38 @@ def scoller(): self.show_frame.bind("", onFrameconfigure) def onFrameconfigure(event): - self.canvas.configure(scrollregion=self.canvas.bbox("all"), width=1000, height=650) + self.canvas.configure( + scrollregion=self.canvas.bbox("all"), width=1000, height=650 + ) def choose_color(): - adata.obsm['coord'][:, 1] = adata.obsm['coord'][:, 1] * (-1) - adata_sample.obsm['coord'][:, 1] = adata_sample.obsm['coord'][:, 1] * (-1) + adata.obsm["coord"][:, 1] = adata.obsm["coord"][:, 1] * (-1) + adata_sample.obsm["coord"][:, 1] = adata_sample.obsm["coord"][:, 1] * ( + -1 + ) self.gene_color_type = color_panel.five_gene_color[random.randint(0, 5)] draw_images() - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + fig_path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + ) figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 4, column=i % 4, sticky=W, pady=0) if self.data_type is None: - self.data_type = '10x' - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + self.data_type = "10x" + fig_path = ( + test_file_path + "/figures/" + self.method_flag + "_" + self.data_type + ) if not os.path.isdir(fig_path): os.mkdir(fig_path) @@ -3788,76 +5344,107 @@ def choose_color(): global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 4, column=i % 4, sticky=W, pady=0) s = i - self.set_frame = ttk.Frame(self.figure_Frame, borderwidth=2, relief="sunken") - self.set_frame.pack(side='right', expand=YES, anchor=N) + self.set_frame = ttk.Frame( + self.figure_Frame, borderwidth=2, relief="sunken" + ) + self.set_frame.pack(side="right", expand=YES, anchor=N) self.set_frame_one = ttk.Frame(self.set_frame) self.set_frame_one.pack(side=TOP, expand=YES) self.set_frame_two = ttk.Frame(self.set_frame) self.set_frame_two.pack(side=TOP, expand=YES) - self.Reset = ttk.Button(self.set_frame_one, text='Reset all colors', command=choose_color, width=12) + self.Reset = ttk.Button( + self.set_frame_one, + text="Reset all colors", + command=choose_color, + width=12, + ) self.Reset.grid(row=0, column=0, sticky=W, pady=0, padx=0) def Reset(): python = sys.executable os.execl(python, python, *sys.argv) - self.Reset = ttk.Button(self.set_frame_one, text='Reset STABox', command=Reset, width=12) + self.Reset = ttk.Button( + self.set_frame_one, text="Reset STABox", command=Reset, width=12 + ) self.Reset.grid(row=0, column=1, sticky=W, pady=0, padx=0) - self.domain_color_label = ttk.Label(self.set_frame_one, text='Reset domain color: ', width=20) + self.domain_color_label = ttk.Label( + self.set_frame_one, text="Reset domain color: ", width=20 + ) self.domain_color_label.grid(row=1, column=0, sticky=W, pady=0) self.Reset_domain_color = ttk.Entry(self.set_frame_one, width=10) self.Reset_domain_color.grid(row=1, column=1, sticky=W, pady=0) - Tooltip(self.Reset_domain_color, "Input value must be int type and in [1:cluster_name]: 2") + Tooltip( + self.Reset_domain_color, + "Input value must be int type and in [1:cluster_name]: 2", + ) self.color_update = None def Reset_single_domain_color(): from tkinter import colorchooser, filedialog + colorvalue = colorchooser.askcolor() color = colorvalue[1] print(color) cluster = self.Reset_domain_color.get() import matplotlib.pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) draw_images() figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - img = Image.open(fig_path + '/' + figures[i]) - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + img = Image.open(fig_path + "/" + figures[i]) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) - self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0, padx=0) + self.result_images.grid( + row=i // 3, column=i % 3, sticky=W, pady=0, padx=0 + ) s = i - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Confirm', - command=Reset_single_domain_color) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, + width=10, + text="Confirm", + command=Reset_single_domain_color, + ) self.Reset_domain_btn.grid(row=1, column=2, sticky=W, pady=10) - self.update_image_label = ttk.Label(self.set_frame_one, text='Reset image dpi: ', width=20) + self.update_image_label = ttk.Label( + self.set_frame_one, text="Reset image dpi: ", width=20 + ) self.update_image_label.grid(row=2, column=0, sticky=W, pady=10) self.update_image_scale = ttk.Entry(self.set_frame_one, width=10) self.update_image_scale.grid(row=2, column=1, sticky=W, pady=10) - Tooltip(self.update_image_scale, "Input value must be int type and >= 300: 300") + Tooltip( + self.update_image_scale, "Input value must be int type and >= 300: 300" + ) def ipdate_hd(): dpi = self.update_image_scale.get() import matplotlib.pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) sc.set_figure_params(dpi=dpi) draw_images() figures = os.listdir(fig_path) - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Save', command=ipdate_hd) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, width=10, text="Save", command=ipdate_hd + ) self.Reset_domain_btn.grid(row=2, column=2, sticky=W, pady=0) - self.gene_visualization_label = ttk.Label(self.set_frame_one, text='Input gene name: ', width=20) + self.gene_visualization_label = ttk.Label( + self.set_frame_one, text="Input gene name: ", width=20 + ) self.gene_visualization_label.grid(row=3, column=0, sticky=W, pady=0) self.gene_visualization_entry = ttk.Entry(self.set_frame_one, width=10) @@ -3868,26 +5455,37 @@ def gene_visualization(): gene = self.gene_visualization_entry.get() if gene not in adata.var_names: raise - sc.pl.spatial(adata, img_key="hires", color=gene, title="$" + gene + "$", show=False, save=gene + '.png') + sc.pl.spatial( + adata, + img_key="hires", + color=gene, + title="$" + gene + "$", + show=False, + save=gene + ".png", + ) global img0 - photo = Image.open(test_file_path + '/figures/show' + gene + '.png') + photo = Image.open(test_file_path + "/figures/show" + gene + ".png") img0 = ImageTk.PhotoImage(photo) img1 = ttk.Label(self.set_frame_two, image=img0) img1.grid(row=0, column=0, sticky=W, pady=0) - if os.path.exists(test_file_path + '/figures/show' + gene + '.png'): - os.remove(test_file_path + '/figures/show' + gene + '.png') + if os.path.exists(test_file_path + "/figures/show" + gene + ".png"): + os.remove(test_file_path + "/figures/show" + gene + ".png") print("yes") else: print("error!") - self.gene_visualization_btn = ttk.Button(self.set_frame_one, width=10, command=gene_visualization, text='Show') + self.gene_visualization_btn = ttk.Button( + self.set_frame_one, width=10, command=gene_visualization, text="Show" + ) self.gene_visualization_btn.grid(row=3, column=2, sticky=W, pady=0) self.result_queue.put(adata) self.result_queue.put(adata_sample) self.result_queue.put(adata_stage) else: - Messagebox.show_warning(title="Attention", message='Waiting for models training!!!') + Messagebox.show_warning( + title="Attention", message="Waiting for models training!!!" + ) def STAGE_10XData_Analysis(self): self.model_train_flag = False @@ -3896,18 +5494,20 @@ def STAGE_10XData_Analysis(self): adata_remove = self.result_queue.get() del adata_remove adata = self.result_queue.get() - if 'GroundTruth' in adata.obs.columns: + if "GroundTruth" in adata.obs.columns: self.label_files_exit = True - adata.obs['layer'] = adata.obs['GroundTruth'] + adata.obs["layer"] = adata.obs["GroundTruth"] adata.obsm["coord"] = adata.obsm["spatial"] - functions = ['generation', 'recovery', '3d_model'] - filepath = test_file_path + '/' + self.method_flag + '_' + self.data_type + '_output' + functions = ["generation", "recovery", "3d_model"] + filepath = ( + test_file_path + "/" + self.method_flag + "_" + self.data_type + "_output" + ) if os.path.isfile(filepath): os.mkdir(filepath) if self.functions_choose not in functions: self.functions_choose = functions[0] if self.data_type is None: - self.data_type = '10x' + self.data_type = "10x" adata_sample, adata_stage = STAGE( adata, save_path=filepath, @@ -3920,35 +5520,39 @@ def STAGE_10XData_Analysis(self): learning_rate=1e-3, w_recon=0.1, w_w=0.1, - w_l1=0.1 + w_l1=0.1, ) sc.pp.pca(adata, n_comps=30) - sc.pp.neighbors(adata, use_rep='X_pca') + sc.pp.neighbors(adata, use_rep="X_pca") sc.tl.umap(adata) sc.pp.pca(adata_sample, n_comps=30) - sc.pp.neighbors(adata_sample, use_rep='X_pca') + sc.pp.neighbors(adata_sample, use_rep="X_pca") sc.tl.umap(adata_sample) sc.pp.pca(adata_stage, n_comps=30) - sc.pp.neighbors(adata_stage, use_rep='X_pca') + sc.pp.neighbors(adata_stage, use_rep="X_pca") sc.tl.umap(adata_stage) - plt.rcParams['font.sans-serif'] = "Arial" - self.gene_color_type = 'viridis' + plt.rcParams["font.sans-serif"] = "Arial" + self.gene_color_type = "viridis" # self.result_queue.put(adata) # self.result_queue.put(adata_sample) # self.result_queue.put(adata_stage) adata.write_h5ad(os.path.join(running_path, "result", "STAGE_raw_output.h5ad")) - adata_sample.write_h5ad(os.path.join(running_path, "result", "STAGE_adata_sample_output.h5ad")) - adata_stage.write_h5ad(os.path.join(running_path, "result", "STAGE_adata_stage_output.h5ad")) + adata_sample.write_h5ad( + os.path.join(running_path, "result", "STAGE_adata_sample_output.h5ad") + ) + adata_stage.write_h5ad( + os.path.join(running_path, "result", "STAGE_adata_stage_output.h5ad") + ) self.pb.stop() - self.pb['value'] = 100 - self.setvar('prog-message', 'STAGE run over!') - self.setvar('End-time', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + self.pb["value"] = 100 + self.setvar("prog-message", "STAGE run over!") + self.setvar("End-time", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) EndTime = datetime.now().replace(microsecond=0) - self.setvar('total-time-cost', EndTime - self.StartTime) + self.setvar("total-time-cost", EndTime - self.StartTime) self.model_train_flag = True self.cluster_flag = True @@ -3960,33 +5564,70 @@ def STAGE_Thread(self): def SpaGCN_show(self): if self.cluster_flag: self.result_flag = True - print(f"self.Mcluster_num type and value are {self.Mcluster_num}, {type(self.Mcluster_num)}") + print( + f"self.Mcluster_num type and value are {self.Mcluster_num}, {type(self.Mcluster_num)}" + ) if self.data_type is None: - self.data_type = '10x' + self.data_type = "10x" def draw_images(sdata): i = 1 temp_path = os.getcwd() os.chdir(test_file_path) from matplotlib import pyplot as plt - plt.rcParams['font.sans-serif'] = "Arial" + + plt.rcParams["font.sans-serif"] = "Arial" plt.rcParams["figure.figsize"] = (3, 3) - path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + '/' + path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + + "/" + ) if self.label_files_exit: - sc.pl.spatial(sdata, color='GroundTruth', title=['Ground Truth'], show=False, spot_size=self.spot_size, - save='SpaGCN_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSpaGCN_' + str(i) + '.png', path + 'SpaGCN_' + str(i) + '.png') + sc.pl.spatial( + sdata, + color="GroundTruth", + title=["Ground Truth"], + show=False, + spot_size=self.spot_size, + save="SpaGCN_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSpaGCN_" + str(i) + ".png", + path + "SpaGCN_" + str(i) + ".png", + ) i = i + 1 domains = "pred" - sc.pl.spatial(sdata, color=domains, title=['SpaGCN-pred'], show=False, spot_size=self.spot_size, - save='SpaGCN_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSpaGCN_' + str(i) + '.png', path + 'SpaGCN_' + str(i) + '.png') + sc.pl.spatial( + sdata, + color=domains, + title=["SpaGCN-pred"], + show=False, + spot_size=self.spot_size, + save="SpaGCN_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSpaGCN_" + str(i) + ".png", + path + "SpaGCN_" + str(i) + ".png", + ) i = i + 1 domains = "refined_pred" - sc.pl.spatial(sdata, color=domains, title=['SpaGCN-refined_pred'], show=False, spot_size=self.spot_size, - save='SpaGCN_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSpaGCN_' + str(i) + '.png', path + 'SpaGCN_' + str(i) + '.png') + sc.pl.spatial( + sdata, + color=domains, + title=["SpaGCN-refined_pred"], + show=False, + spot_size=self.spot_size, + save="SpaGCN_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSpaGCN_" + str(i) + ".png", + path + "SpaGCN_" + str(i) + ".png", + ) # plt.rcParams["figure.figsize"] = (3, 3) # sc.pl.umap(adata, color="mclust", title=['SpaGCN-mclust-umap'], show=False, s=6, @@ -4001,27 +5642,61 @@ def draw_images(sdata): # path + '/SpaGCN_mclust.png') i = i + 1 - sc.pl.umap(adata, color="louvain", title=['SpaGCN-louvain-umap'], show=False, s=6, - save='SpaGCN_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSpaGCN_' + str(i) + '.png', - path + '/SpaGCN_louvain_umap.png') + sc.pl.umap( + adata, + color="louvain", + title=["SpaGCN-louvain-umap"], + show=False, + s=6, + save="SpaGCN_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSpaGCN_" + str(i) + ".png", + path + "/SpaGCN_louvain_umap.png", + ) i = i + 1 - sc.pl.spatial(adata, color="louvain", title=['SpaGCN-louvain'], show=False, - spot_size=self.spot_size, save='SpaGCN_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSpaGCN_' + str(i) + '.png', - path + '/SpaGCN_louvain.png') + sc.pl.spatial( + adata, + color="louvain", + title=["SpaGCN-louvain"], + show=False, + spot_size=self.spot_size, + save="SpaGCN_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSpaGCN_" + str(i) + ".png", + path + "/SpaGCN_louvain.png", + ) else: domains = "pred" - sc.pl.spatial(sdata, color=domains, title=['SpaGCN-pred'], show=False, spot_size=self.spot_size, - save='SpaGCN_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSpaGCN_' + str(i) + '.png', path + 'SpaGCN_' + str(i) + '.png') + sc.pl.spatial( + sdata, + color=domains, + title=["SpaGCN-pred"], + show=False, + spot_size=self.spot_size, + save="SpaGCN_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSpaGCN_" + str(i) + ".png", + path + "SpaGCN_" + str(i) + ".png", + ) i = i + 1 domains = "refined_pred" - sc.pl.spatial(sdata, color=domains, title=['SpaGCN-refined_pred'], show=False, spot_size=self.spot_size, - save='SpaGCN_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSpaGCN_' + str(i) + '.png', path + 'SpaGCN_' + str(i) + '.png') + sc.pl.spatial( + sdata, + color=domains, + title=["SpaGCN-refined_pred"], + show=False, + spot_size=self.spot_size, + save="SpaGCN_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSpaGCN_" + str(i) + ".png", + path + "SpaGCN_" + str(i) + ".png", + ) # i = i + 1 # plt.rcParams["figure.figsize"] = (3, 3) @@ -4037,25 +5712,45 @@ def draw_images(sdata): # path + '/SpaGCN_mclust.png') i = i + 1 - sc.pl.umap(adata, color="louvain", title=['SpaGCN-louvain-umap'], show=False, s=6, - save='SpaGCN_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSpaGCN_' + str(i) + '.png', - path + '/SpaGCN_louvain_umap.png') + sc.pl.umap( + adata, + color="louvain", + title=["SpaGCN-louvain-umap"], + show=False, + s=6, + save="SpaGCN_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSpaGCN_" + str(i) + ".png", + path + "/SpaGCN_louvain_umap.png", + ) i = i + 1 - sc.pl.spatial(adata, color="louvain", title=['SpaGCN-louvain'], show=False, - spot_size=self.spot_size, save='SpaGCN_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSpaGCN_' + str(i) + '.png', - path + '/SpaGCN_louvain.png') + sc.pl.spatial( + adata, + color="louvain", + title=["SpaGCN-louvain"], + show=False, + spot_size=self.spot_size, + save="SpaGCN_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSpaGCN_" + str(i) + ".png", + path + "/SpaGCN_louvain.png", + ) os.chdir(temp_path) - print(f'Result images are saved in : {test_file_path}/figures') + print(f"Result images are saved in : {test_file_path}/figures") def scoller(): - self.figure_ybar = ttk.Scrollbar(self.figure_Frame, orient=VERTICAL, cursor='draft_small') + self.figure_ybar = ttk.Scrollbar( + self.figure_Frame, orient=VERTICAL, cursor="draft_small" + ) self.figure_ybar.pack(side=RIGHT, fill=Y) self.figure_ybar.config(command=self.canvas.yview) - self.figure_xbar = ttk.Scrollbar(self.figure_Frame, orient=HORIZONTAL, cursor='draft_small') + self.figure_xbar = ttk.Scrollbar( + self.figure_Frame, orient=HORIZONTAL, cursor="draft_small" + ) self.figure_xbar.pack(side=BOTTOM, fill=X) self.figure_xbar.config(command=self.canvas.xview) @@ -4069,38 +5764,44 @@ def scoller(): self.show_frame.bind("", onFrameconfigure) def onFrameconfigure(event): - self.canvas.configure(scrollregion=self.canvas.bbox("all"), width=1000, height=650) + self.canvas.configure( + scrollregion=self.canvas.bbox("all"), width=1000, height=650 + ) def choose_color(): colorvalue = colorchooser.askcolor() color_list = [] color = colorvalue[1] - color_lens = [adata.uns['louvain_colors'], adata.uns['pred_colors'], adata.uns['refined_pred_colors']] + color_lens = [ + adata.uns["louvain_colors"], + adata.uns["pred_colors"], + adata.uns["refined_pred_colors"], + ] max_len = max(color_lens, key=len) if len(max_len) > self.cluster_value: self.cluster_value = len(max_len) print(color) - if color[1:3] == 'ff': + if color[1:3] == "ff": color_list.append(color) list = random.sample(color_panel.FF_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == 'cc': + elif color[1:3] == "cc": color_list.append(color) list = random.sample(color_panel.CC_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '99': + elif color[1:3] == "99": color_list.append(color) list = random.sample(color_panel.NN_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '66': + elif color[1:3] == "66": color_list.append(color) list = random.sample(color_panel.SS_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '33': + elif color[1:3] == "33": color_list.append(color) list = random.sample(color_panel.TT_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '00': + elif color[1:3] == "00": color_list.append(color) list = random.sample(color_panel.ZZ_color, self.cluster_value) color_list = color_list + list @@ -4112,25 +5813,43 @@ def choose_color(): print(color_list) # sdata = adata if self.label_files_exit: - adata.uns['GroundTruth_colors'] = color_list - adata.uns['pred_colors'] = color_list[:len(adata.uns['pred_colors'])] - adata.uns['refined_pred_colors'] = color_list[:len(adata.uns['refined_pred_colors'])] - adata.uns['louvain_colors'] = color_list[:len(adata.uns['louvain_colors'])] + adata.uns["GroundTruth_colors"] = color_list + adata.uns["pred_colors"] = color_list[: len(adata.uns["pred_colors"])] + adata.uns["refined_pred_colors"] = color_list[ + : len(adata.uns["refined_pred_colors"]) + ] + adata.uns["louvain_colors"] = color_list[ + : len(adata.uns["louvain_colors"]) + ] # adata.uns['mclust_colors'] = color_list[:len(adata.uns['mclust_colors'])] self.color_reset = color_list os.chdir(Raw_PATH) draw_images(adata) - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + '/' + fig_path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + + "/" + ) figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0) - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + '/' + fig_path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + + "/" + ) if not os.path.isdir(fig_path): os.mkdir(fig_path) @@ -4145,35 +5864,54 @@ def choose_color(): self.canvas = ttk.Canvas(self.figure_Frame) self.show_frame = ttk.Frame(self.canvas) scoller() - self.set_frame = ttk.Frame(self.figure_Frame, borderwidth=2, relief="sunken") - self.set_frame.pack(side='right', expand=YES, anchor=N) + self.set_frame = ttk.Frame( + self.figure_Frame, borderwidth=2, relief="sunken" + ) + self.set_frame.pack(side="right", expand=YES, anchor=N) self.set_frame_one = ttk.Frame(self.set_frame) self.set_frame_one.pack(side=TOP, expand=YES) self.set_frame_two = ttk.Frame(self.set_frame) self.set_frame_two.pack(side=TOP, expand=YES) - self.Reset = ttk.Button(self.set_frame_one, text='Reset all colors', command=choose_color, width=12) + self.Reset = ttk.Button( + self.set_frame_one, + text="Reset all colors", + command=choose_color, + width=12, + ) self.Reset.grid(row=0, column=0, sticky=W, pady=0, padx=0) - self.domain_color_label = ttk.Label(self.set_frame_one, text='Reset domain color: ', width=20) + self.domain_color_label = ttk.Label( + self.set_frame_one, text="Reset domain color: ", width=20 + ) self.domain_color_label.grid(row=1, column=0, sticky=W, pady=0) self.Reset_domain_color = ttk.Entry(self.set_frame_one, width=10) self.Reset_domain_color.grid(row=1, column=1, sticky=W, pady=0) - Tooltip(self.Reset_domain_color, "Input value must be int type and in [1:cluster_name]: 2") + Tooltip( + self.Reset_domain_color, + "Input value must be int type and in [1:cluster_name]: 2", + ) self.color_update = None def Reset_single_domain_color(): from tkinter import colorchooser, filedialog + colorvalue = colorchooser.askcolor() color = colorvalue[1] print(color) cluster = self.Reset_domain_color.get() self.color_reset[int(cluster) - 1] = color - adata.uns['louvain_colors'] = self.color_reset[:len(adata.uns['louvain_colors'])] + adata.uns["louvain_colors"] = self.color_reset[ + : len(adata.uns["louvain_colors"]) + ] # adata.uns['mclust_colors'] = self.color_reset[:len(adata.uns['mclust_colors'])] - adata.uns['pred_colors'] = self.color_reset[:len(adata.uns['pred_colors'])] - adata.uns['refined_pred_colors'] = self.color_reset[:len(adata.uns['refined_pred_colors'])] + adata.uns["pred_colors"] = self.color_reset[ + : len(adata.uns["pred_colors"]) + ] + adata.uns["refined_pred_colors"] = self.color_reset[ + : len(adata.uns["refined_pred_colors"]) + ] self.color_update = self.color_reset draw_images(adata) @@ -4181,33 +5919,48 @@ def Reset_single_domain_color(): global image_list image_list = [] for i in range(len(figures)): - img = Image.open(fig_path + '/' + figures[i]) + img = Image.open(fig_path + "/" + figures[i]) print(img.size) - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) - self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0, padx=0) + self.result_images.grid( + row=i // 3, column=i % 3, sticky=W, pady=0, padx=0 + ) s = i - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Confirm', - command=Reset_single_domain_color) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, + width=10, + text="Confirm", + command=Reset_single_domain_color, + ) self.Reset_domain_btn.grid(row=1, column=2, sticky=W, pady=10) - self.update_image_label = ttk.Label(self.set_frame_one, text='Reset image dpi: ', width=20) + self.update_image_label = ttk.Label( + self.set_frame_one, text="Reset image dpi: ", width=20 + ) self.update_image_label.grid(row=2, column=0, sticky=W, pady=10) self.update_image_scale = ttk.Entry(self.set_frame_one, width=10) self.update_image_scale.grid(row=2, column=1, sticky=W, pady=10) - Tooltip(self.update_image_scale, "Input value must be int type and >= 300: 300") + Tooltip( + self.update_image_scale, "Input value must be int type and >= 300: 300" + ) def ipdate_hd(): dpi = self.update_image_scale.get() import matplotlib.pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) sc.set_figure_params(dpi=dpi) draw_images(adata) - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Save', command=ipdate_hd) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, width=10, text="Save", command=ipdate_hd + ) self.Reset_domain_btn.grid(row=2, column=2, sticky=W, pady=0) - self.gene_visualization_label = ttk.Label(self.set_frame_one, text='Input gene name: ', width=20) + self.gene_visualization_label = ttk.Label( + self.set_frame_one, text="Input gene name: ", width=20 + ) self.gene_visualization_label.grid(row=3, column=0, sticky=W, pady=0) self.gene_visualization_entry = ttk.Entry(self.set_frame_one, width=10) @@ -4220,23 +5973,34 @@ def gene_visualization(): if gene not in adata.var_names: raise "gene not in adata!" else: - sc.pl.spatial(adata, img_key="hires", color=gene, title="$" + gene + "$", - show=False, save=gene + '.png', sopt_size=self.spot_size) + sc.pl.spatial( + adata, + img_key="hires", + color=gene, + title="$" + gene + "$", + show=False, + save=gene + ".png", + sopt_size=self.spot_size, + ) global img0 - photo = Image.open(test_file_path + '/figures/show' + gene + '.png') + photo = Image.open(test_file_path + "/figures/show" + gene + ".png") img0 = ImageTk.PhotoImage(photo) img1 = ttk.Label(self.set_frame_two, image=img0) img1.grid(row=0, column=0, sticky=W, pady=0) - if os.path.exists(test_file_path + '/figures/show' + gene + '.png'): - os.remove(test_file_path + '/figures/show' + gene + '.png') + if os.path.exists(test_file_path + "/figures/show" + gene + ".png"): + os.remove(test_file_path + "/figures/show" + gene + ".png") print("Figures exits") else: print("Figures no exits!") pass except: - Messagebox.show_error("Python Error", "Make sure gene name in dataset") + Messagebox.show_error( + "Python Error", "Make sure gene name in dataset" + ) - self.gene_visualization_btn = ttk.Button(self.set_frame_one, width=10, command=gene_visualization, text='Show') + self.gene_visualization_btn = ttk.Button( + self.set_frame_one, width=10, command=gene_visualization, text="Show" + ) self.gene_visualization_btn.grid(row=3, column=2, sticky=W, pady=0) global image_list @@ -4244,21 +6008,26 @@ def gene_visualization(): image_list = [] s = 0 for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0) s = i def VIEW_3D(): import webbrowser - self.web_Server_Thread('/DLPFC/webcache', 8029) - webbrowser.open('http://127.0.0.1:8029/') - self.Reset = ttk.Button(self.set_frame_one, text='3D VIEW', command=VIEW_3D, width=10) + self.web_Server_Thread("/DLPFC/webcache", 8029) + webbrowser.open("http://127.0.0.1:8029/") + + self.Reset = ttk.Button( + self.set_frame_one, text="3D VIEW", command=VIEW_3D, width=10 + ) self.Reset.grid(row=0, column=1, sticky=W, pady=0, padx=(0, 100)) self.result_queue.put(adata) else: - Messagebox.show_warning(title="Attention", message='Waiting for models training!!!') + Messagebox.show_warning( + title="Attention", message="Waiting for models training!!!" + ) def SpaGCN_10XData_Analysis(self): try: @@ -4267,70 +6036,107 @@ def SpaGCN_10XData_Analysis(self): for i in range(self.result_queue.qsize() - 1): adata_remove = self.result_queue.get() del adata_remove - file_path = self.file_path.rsplit('/', 1)[-2] - tif_image = glob.glob(file_path + '/*.tif') + file_path = self.file_path.rsplit("/", 1)[-2] + tif_image = glob.glob(file_path + "/*.tif") histology = False adata = self.result_queue.get() - if 'GroundTruth' in adata.obs.columns: + if "GroundTruth" in adata.obs.columns: self.label_files_exit = True - x_array = adata.obsm['spatial'][:, 0].tolist() - y_array = adata.obsm['spatial'][:, 1].tolist() - x_pixel = adata.obsm['spatial'][:, 0].tolist() - y_pixel = adata.obsm['spatial'][:, 1].tolist() + x_array = adata.obsm["spatial"][:, 0].tolist() + y_array = adata.obsm["spatial"][:, 1].tolist() + x_pixel = adata.obsm["spatial"][:, 0].tolist() + y_pixel = adata.obsm["spatial"][:, 1].tolist() spg.prefilter_genes(adata, min_cells=3) spg.prefilter_specialgenes(adata) - if self.data_type == '10x': + if self.data_type == "10x": sc.pp.normalize_per_cell(adata) sc.pp.log1p(adata) if len(tif_image) > 0: histology = True img = cv2.imread(tif_image[0]) - adj = spg.calculate_adj_matrix(x=x_pixel, y=y_pixel, x_pixel=x_pixel, y_pixel=y_pixel, image=img, - beta=int(self.rad_cutoff_value), alpha=1, histology=histology) + adj = spg.calculate_adj_matrix( + x=x_pixel, + y=y_pixel, + x_pixel=x_pixel, + y_pixel=y_pixel, + image=img, + beta=int(self.rad_cutoff_value), + alpha=1, + histology=histology, + ) else: - adj = spg.calculate_adj_matrix(x=x_pixel, y=y_pixel, histology=histology) - l = spg.search_l(float(self.genes), adj, start=0.01, end=1000, tol=0.01, max_run=100) + adj = spg.calculate_adj_matrix( + x=x_pixel, y=y_pixel, histology=histology + ) + l = spg.search_l( + float(self.genes), adj, start=0.01, end=1000, tol=0.01, max_run=100 + ) # If the number of clusters known, we can use the spg.search_res() fnction to search for suitable resolution(optional) # For this toy data, we set the number of clusters=7 since this tissue has 7 layers # n_clusters = 7 r_seed = t_seed = n_seed = 100 - res = spg.search_res(adata, adj, l, int(self.cluster_value), start=0.7, step=0.1, tol=5e-3, lr=0.05, - max_epochs=20, r_seed=r_seed, t_seed=t_seed, n_seed=n_seed) + res = spg.search_res( + adata, + adj, + l, + int(self.cluster_value), + start=0.7, + step=0.1, + tol=5e-3, + lr=0.05, + max_epochs=20, + r_seed=r_seed, + t_seed=t_seed, + n_seed=n_seed, + ) clf = spg.SpaGCN() clf.set_l(l) random.seed(r_seed) torch.manual_seed(t_seed) np.random.seed(n_seed) - clf.train(adata, adj, init_spa=True, init="louvain", res=res, tol=5e-3, lr=0.05, max_epochs=int(self.alpha_value)) + clf.train( + adata, + adj, + init_spa=True, + init="louvain", + res=res, + tol=5e-3, + lr=0.05, + max_epochs=int(self.alpha_value), + ) y_pred, prob = clf.predict() - adata.obsm['SpaGCN'] = clf.embed + adata.obsm["SpaGCN"] = clf.embed adata.obs["pred"] = y_pred - adata.obs["pred"] = adata.obs["pred"].astype('category') + adata.obs["pred"] = adata.obs["pred"].astype("category") # shape="hexagon" for Visium data, "square" for ST data. adj_2d = spg.calculate_adj_matrix(x=x_array, y=y_array, histology=False) - refined_pred = spg.refine(sample_id=adata.obs.index.tolist(), pred=adata.obs["pred"].tolist(), dis=adj_2d, - shape="hexagon") + refined_pred = spg.refine( + sample_id=adata.obs.index.tolist(), + pred=adata.obs["pred"].tolist(), + dis=adj_2d, + shape="hexagon", + ) adata.obs["refined_pred"] = refined_pred - adata.obs["refined_pred"] = adata.obs["refined_pred"].astype('category') - adata.obs['x_pixel'] = adata.obsm['spatial'][:, 1] - adata.obs['y_pixel'] = adata.obsm['spatial'][:, 0] - sc.pp.neighbors(adata, use_rep='SpaGCN') + adata.obs["refined_pred"] = adata.obs["refined_pred"].astype("category") + adata.obs["x_pixel"] = adata.obsm["spatial"][:, 1] + adata.obs["y_pixel"] = adata.obsm["spatial"][:, 0] + sc.pp.neighbors(adata, use_rep="SpaGCN") sc.tl.umap(adata) # self.result_queue.put(adata) adata.write_h5ad(os.path.join(running_path, "result", "SpaGCN_output.h5ad")) self.pb.stop() - self.pb['value'] = 100 - self.setvar('prog-message', 'SpaGCN run over!') - self.setvar('End-time', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + self.pb["value"] = 100 + self.setvar("prog-message", "SpaGCN run over!") + self.setvar("End-time", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) EndTime = datetime.now().replace(microsecond=0) - self.setvar('total-time-cost', EndTime - self.StartTime) + self.setvar("total-time-cost", EndTime - self.StartTime) self.model_train_flag = True self.cluster_flag = True except: self.model_train_flag = False - raise 'Check whether the files exists!' + raise "Check whether the files exists!" def SpaGCN_Thread(self): T = threading.Thread(target=self.SpaGCN_10XData_Analysis) @@ -4342,34 +6148,65 @@ def SEDR_show(self): if self.cluster_flag: self.result_flag = True if self.data_type is None: - self.data_type = '10x' + self.data_type = "10x" def draw_images(sdata): temp_path = os.getcwd() os.chdir(test_file_path) from matplotlib import pyplot as plt - plt.rcParams['font.sans-serif'] = "Arial" + + plt.rcParams["font.sans-serif"] = "Arial" plt.rcParams["figure.figsize"] = (3, 3) domains = ["SEDR_leiden", "SEDR_mclust", "SEDR_kmeans"] - path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + '/' + path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + + "/" + ) for i in domains: - sc.pl.spatial(sdata, color=i, title=i, show=False, save='SEDR_' + i + '.png', spot_size=self.spot_size) - shutil.move(test_file_path + '/figures/showSEDR_' + i + '.png', path + i + '.png') + sc.pl.spatial( + sdata, + color=i, + title=i, + show=False, + save="SEDR_" + i + ".png", + spot_size=self.spot_size, + ) + shutil.move( + test_file_path + "/figures/showSEDR_" + i + ".png", + path + i + ".png", + ) - sc.pl.umap(adata, color=i, title=f'{i}_umap', show=False, s=6, - save='SEDR_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSEDR_' + i + '.png', path + i + '_umap.png') + sc.pl.umap( + adata, + color=i, + title=f"{i}_umap", + show=False, + s=6, + save="SEDR_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSEDR_" + i + ".png", + path + i + "_umap.png", + ) - print(f'Result images are saved in : {test_file_path}/figures') + print(f"Result images are saved in : {test_file_path}/figures") os.chdir(temp_path) def scoller(): - self.figure_ybar = ttk.Scrollbar(self.figure_Frame, orient=VERTICAL, cursor='draft_small') + self.figure_ybar = ttk.Scrollbar( + self.figure_Frame, orient=VERTICAL, cursor="draft_small" + ) self.figure_ybar.pack(side=RIGHT, fill=Y) self.figure_ybar.config(command=self.canvas.yview) - self.figure_xbar = ttk.Scrollbar(self.figure_Frame, orient=HORIZONTAL, cursor='draft_small') + self.figure_xbar = ttk.Scrollbar( + self.figure_Frame, orient=HORIZONTAL, cursor="draft_small" + ) self.figure_xbar.pack(side=BOTTOM, fill=X) self.figure_xbar.config(command=self.canvas.xview) @@ -4383,36 +6220,41 @@ def scoller(): self.show_frame.bind("", onFrameconfigure) def onFrameconfigure(event): - self.canvas.configure(scrollregion=self.canvas.bbox("all"), width=1000, height=650) + self.canvas.configure( + scrollregion=self.canvas.bbox("all"), width=1000, height=650 + ) def choose_color(): colorvalue = colorchooser.askcolor() color_list = [] color = colorvalue[1] print(color) - self.cluster_value = max(len(adata.uns['SEDR_leiden_colors']), len(adata.uns['SEDR_mclust_colors']), - len(adata.uns['SEDR_kmeans_colors'])) - if color[1:3] == 'ff': + self.cluster_value = max( + len(adata.uns["SEDR_leiden_colors"]), + len(adata.uns["SEDR_mclust_colors"]), + len(adata.uns["SEDR_kmeans_colors"]), + ) + if color[1:3] == "ff": color_list.append(color) list = random.sample(color_panel.FF_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == 'cc': + elif color[1:3] == "cc": color_list.append(color) list = random.sample(color_panel.CC_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '99': + elif color[1:3] == "99": color_list.append(color) list = random.sample(color_panel.NN_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '66': + elif color[1:3] == "66": color_list.append(color) list = random.sample(color_panel.SS_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '33': + elif color[1:3] == "33": color_list.append(color) list = random.sample(color_panel.TT_color, self.cluster_value) color_list = color_list + list - elif color[1:3] == '00': + elif color[1:3] == "00": color_list.append(color) list = random.sample(color_panel.ZZ_color, self.cluster_value) color_list = color_list + list @@ -4422,23 +6264,43 @@ def choose_color(): color_list = color_list + list print(color_list) - adata.uns['SEDR_leiden_colors'] = color_list[:len(adata.uns['SEDR_leiden_colors'])] - adata.uns['SEDR_mclust_colors'] = color_list[:len(adata.uns['SEDR_mclust_colors'])] - adata.uns['SEDR_kmeans_colors'] = color_list[:len(adata.uns['SEDR_kmeans_colors'])] + adata.uns["SEDR_leiden_colors"] = color_list[ + : len(adata.uns["SEDR_leiden_colors"]) + ] + adata.uns["SEDR_mclust_colors"] = color_list[ + : len(adata.uns["SEDR_mclust_colors"]) + ] + adata.uns["SEDR_kmeans_colors"] = color_list[ + : len(adata.uns["SEDR_kmeans_colors"]) + ] self.color_reset = color_list os.chdir(Raw_PATH) draw_images(adata) - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + '/' + fig_path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + + "/" + ) figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0) - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + '/' + fig_path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + + "/" + ) if not os.path.isdir(fig_path): os.mkdir(fig_path) @@ -4468,7 +6330,6 @@ def choose_color(): # adata.obs['SEDR_kmeans'] = adata.obs['SEDR_kmeans'].astype('int') # adata.obs['SEDR_kmeans'] = adata.obs['SEDR_kmeans'].astype('category') - draw_images(adata) self.figure_Frame = ttk.Frame(self.right_panel) self.figure_Frame.pack(side=TOP, fill=X, expand=YES) @@ -4477,71 +6338,105 @@ def choose_color(): self.show_frame = ttk.Frame(self.canvas) scoller() - self.set_frame = ttk.Frame(self.figure_Frame, borderwidth=2, relief="sunken") - self.set_frame.pack(side='right', expand=YES, anchor=N) + self.set_frame = ttk.Frame( + self.figure_Frame, borderwidth=2, relief="sunken" + ) + self.set_frame.pack(side="right", expand=YES, anchor=N) self.set_frame_one = ttk.Frame(self.set_frame) self.set_frame_one.pack(side=TOP, expand=YES) self.set_frame_two = ttk.Frame(self.set_frame) self.set_frame_two.pack(side=TOP, expand=YES) - self.Reset = ttk.Button(self.set_frame_one, text='Reset all colors', command=choose_color, width=12) + self.Reset = ttk.Button( + self.set_frame_one, + text="Reset all colors", + command=choose_color, + width=12, + ) self.Reset.grid(row=0, column=0, sticky=W, pady=0, padx=0) - self.domain_color_label = ttk.Label(self.set_frame_one, text='Reset domain color: ', width=20) + self.domain_color_label = ttk.Label( + self.set_frame_one, text="Reset domain color: ", width=20 + ) self.domain_color_label.grid(row=1, column=0, sticky=W, pady=0) self.Reset_domain_color = ttk.Entry(self.set_frame_one, width=10) self.Reset_domain_color.grid(row=1, column=1, sticky=W, pady=0) - Tooltip(self.Reset_domain_color, "Input value must be int type and in [1:cluster_name]: 2") + Tooltip( + self.Reset_domain_color, + "Input value must be int type and in [1:cluster_name]: 2", + ) self.color_update = None def Reset_single_domain_color(): from tkinter import colorchooser, filedialog + colorvalue = colorchooser.askcolor() color = colorvalue[1] print(color) cluster = self.Reset_domain_color.get() print(cluster) self.color_reset[int(cluster) - 1] = color - adata.uns['SEDR_leiden_colors'] = self.color_reset[:len(adata.uns['SEDR_leiden_colors'])] - adata.uns['SEDR_mclust_colors'] = self.color_reset[:len(adata.uns['SEDR_mclust_colors'])] - adata.uns['SEDR_kmeans_colors'] = self.color_reset[:len(adata.uns['SEDR_kmeans_colors'])] + adata.uns["SEDR_leiden_colors"] = self.color_reset[ + : len(adata.uns["SEDR_leiden_colors"]) + ] + adata.uns["SEDR_mclust_colors"] = self.color_reset[ + : len(adata.uns["SEDR_mclust_colors"]) + ] + adata.uns["SEDR_kmeans_colors"] = self.color_reset[ + : len(adata.uns["SEDR_kmeans_colors"]) + ] draw_images(adata) figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - img = Image.open(fig_path + '/' + figures[i]) + img = Image.open(fig_path + "/" + figures[i]) print(img.size) - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) - self.result_images.grid(row=i // 4, column=i % 4, sticky=W, pady=0, padx=0) + self.result_images.grid( + row=i // 4, column=i % 4, sticky=W, pady=0, padx=0 + ) s = i - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Confirm', - command=Reset_single_domain_color) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, + width=10, + text="Confirm", + command=Reset_single_domain_color, + ) self.Reset_domain_btn.grid(row=1, column=2, sticky=W, pady=10) - self.update_image_label = ttk.Label(self.set_frame_one, text='Reset image dpi: ', width=20) + self.update_image_label = ttk.Label( + self.set_frame_one, text="Reset image dpi: ", width=20 + ) self.update_image_label.grid(row=2, column=0, sticky=W, pady=10) self.update_image_scale = ttk.Entry(self.set_frame_one, width=10) self.update_image_scale.grid(row=2, column=1, sticky=W, pady=10) - Tooltip(self.update_image_scale, "Input value must be int type and >= 300: 300") + Tooltip( + self.update_image_scale, "Input value must be int type and >= 300: 300" + ) def ipdate_hd(): dpi = self.update_image_scale.get() print(dpi) import matplotlib.pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) sc.set_figure_params(dpi=dpi) draw_images(adata) figures = os.listdir(fig_path) print(len(figures)) - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Save', command=ipdate_hd) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, width=10, text="Save", command=ipdate_hd + ) self.Reset_domain_btn.grid(row=2, column=2, sticky=W, pady=0) - self.gene_visualization_label = ttk.Label(self.set_frame_one, text='Input gene name: ', width=20) + self.gene_visualization_label = ttk.Label( + self.set_frame_one, text="Input gene name: ", width=20 + ) self.gene_visualization_label.grid(row=3, column=0, sticky=W, pady=0) self.gene_visualization_entry = ttk.Entry(self.set_frame_one, width=10) @@ -4551,23 +6446,34 @@ def ipdate_hd(): def gene_visualization(): try: gene = self.gene_visualization_entry.get() - sc.pl.spatial(adata, img_key="hires", color=gene, title="$" + gene + "$", - show=False, save=gene + '.png', sopt_size=50) + sc.pl.spatial( + adata, + img_key="hires", + color=gene, + title="$" + gene + "$", + show=False, + save=gene + ".png", + sopt_size=50, + ) global img0 - photo = Image.open(test_file_path + '/figures/show' + gene + '.png') + photo = Image.open(test_file_path + "/figures/show" + gene + ".png") img0 = ImageTk.PhotoImage(photo) img1 = ttk.Label(self.set_frame_two, image=img0) img1.grid(row=0, column=0, sticky=W, pady=0) - if os.path.exists(test_file_path + '/figures/show' + gene + '.png'): - os.remove(test_file_path + '/figures/show' + gene + '.png') + if os.path.exists(test_file_path + "/figures/show" + gene + ".png"): + os.remove(test_file_path + "/figures/show" + gene + ".png") print("Figures exits") else: print("Figures no exits!") pass except: - Messagebox.show_error("Python Error", "Make sure gene name in dataset") + Messagebox.show_error( + "Python Error", "Make sure gene name in dataset" + ) - self.gene_visualization_btn = ttk.Button(self.set_frame_one, width=10, command=gene_visualization, text='Show') + self.gene_visualization_btn = ttk.Button( + self.set_frame_one, width=10, command=gene_visualization, text="Show" + ) self.gene_visualization_btn.grid(row=3, column=2, sticky=W, pady=0) global image_list @@ -4575,21 +6481,26 @@ def gene_visualization(): image_list = [] s = 0 for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 4, column=i % 4, sticky=W, pady=0) s = i def VIEW_3D(): import webbrowser - self.web_Server_Thread('/DLPFC/webcache', 8029) - webbrowser.open('http://127.0.0.1:8029/') - self.Reset = ttk.Button(self.set_frame_one, text='3D VIEW', command=VIEW_3D, width=10) + self.web_Server_Thread("/DLPFC/webcache", 8029) + webbrowser.open("http://127.0.0.1:8029/") + + self.Reset = ttk.Button( + self.set_frame_one, text="3D VIEW", command=VIEW_3D, width=10 + ) self.Reset.grid(row=0, column=1, sticky=W, pady=0, padx=(0, 100)) self.result_queue.put(adata) else: - Messagebox.show_warning(title="Attention", message='Waiting for models training!!!') + Messagebox.show_warning( + title="Attention", message="Waiting for models training!!!" + ) def SEDR_Data_Analysis(self): try: @@ -4599,20 +6510,25 @@ def SEDR_Data_Analysis(self): adata_remove = self.result_queue.get() del adata_remove adata = self.result_queue.get() - adata.obs['total_exp'] = adata.X.sum(axis=1) + adata.obs["total_exp"] = adata.X.sum(axis=1) adata.var_names_make_unique() if self.data_type is None: - self.data_type = '10x' - if self.data_type == '10x': - adata_X = adata_preprocess(adata, min_cells=5, pca_n_comps=params.cell_feat_dim) + self.data_type = "10x" + if self.data_type == "10x": + adata_X = adata_preprocess( + adata, min_cells=5, pca_n_comps=params.cell_feat_dim + ) else: from sklearn.decomposition import PCA + params.k = 5 adata_X = PCA(n_components=200, random_state=42).fit_transform(adata.X) - adata.obsm['X_pca'] = adata_X - graph_dict = graph_construction(adata.obsm['spatial'], adata.shape[0], params) + adata.obsm["X_pca"] = adata_X + graph_dict = graph_construction( + adata.obsm["spatial"], adata.shape[0], params + ) params.cell_num = adata.shape[0] - print('==== Graph Construction Finished') + print("==== Graph Construction Finished") # ################## Model training sedr_net = SEDR_Train(adata_X, graph_dict, params) @@ -4624,25 +6540,27 @@ def SEDR_Data_Analysis(self): sedr_feat, _, _, _ = sedr_net.process() adata_sedr = anndata.AnnData(sedr_feat) - adata_sedr.obsm['spatial'] = adata.obsm['spatial'] + adata_sedr.obsm["spatial"] = adata.obsm["spatial"] adata_sedr.obs_names = adata.obs_names sc.pp.neighbors(adata_sedr, n_neighbors=params.eval_graph_n) sc.tl.umap(adata_sedr) # self.result_queue.put(adata_sedr) - adata_sedr.write_h5ad(os.path.join(running_path, "result", "SEDR_output.h5ad")) + adata_sedr.write_h5ad( + os.path.join(running_path, "result", "SEDR_output.h5ad") + ) self.pb.stop() - self.pb['value'] = 100 - self.setvar('prog-message', 'SEDR run over!') - self.setvar('End-time', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + self.pb["value"] = 100 + self.setvar("prog-message", "SEDR run over!") + self.setvar("End-time", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) EndTime = datetime.now().replace(microsecond=0) - self.setvar('total-time-cost', EndTime - self.StartTime) + self.setvar("total-time-cost", EndTime - self.StartTime) self.model_train_flag = True self.cluster_flag = True except: self.model_train_flag = False - raise 'Check whether the files exists!' + raise "Check whether the files exists!" def SEDR_Thread(self): T = threading.Thread(target=self.SEDR_Data_Analysis) @@ -4653,110 +6571,234 @@ def SCANPY_show(self): if self.cluster_flag: self.result_flag = True if self.data_type is None: - self.data_type = '10x' - plt.rcParams['font.sans-serif'] = "Arial" - self.gene_color_type = 'viridis' + self.data_type = "10x" + plt.rcParams["font.sans-serif"] = "Arial" + self.gene_color_type = "viridis" def draw_images(): i = 1 os.chdir(Raw_PATH) from matplotlib import pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) - path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + ) if self.label_files_exit: - sc.pl.spatial(adata, img_key="hires", color="GroundTruth", title='Ground Truth', show=False, - save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.spatial( + adata, + img_key="hires", + color="GroundTruth", + title="Ground Truth", + show=False, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(adata, color="SCANPY_leiden", title='SCANPY-leiden-umap', show=False, s=6, save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.umap( + adata, + color="SCANPY_leiden", + title="SCANPY-leiden-umap", + show=False, + s=6, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) i = i + 1 - sc.pl.spatial(adata, color="SCANPY_leiden", title='SCANPY-leiden', show=False, save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.spatial( + adata, + color="SCANPY_leiden", + title="SCANPY-leiden", + show=False, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(adata, color="SCANPY_kmeans", title='SCANPY-kmeans-umap', show=False, s=6, - save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.umap( + adata, + color="SCANPY_kmeans", + title="SCANPY-kmeans-umap", + show=False, + s=6, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) i = i + 1 - sc.pl.spatial(adata, color="SCANPY_kmeans", title='SCANPY', show=False, - save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.spatial( + adata, + color="SCANPY_kmeans", + title="SCANPY", + show=False, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) adata.obs.GroundTruth = adata.obs.GroundTruth.astype(str) i = i + 1 - sc.tl.paga(adata, groups='GroundTruth') + sc.tl.paga(adata, groups="GroundTruth") plt.rcParams["figure.figsize"] = (4, 3) - sc.pl.paga(adata, color="GroundTruth", title='PAGA', show=False, save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/pagaSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.paga( + adata, + color="GroundTruth", + title="PAGA", + show=False, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/pagaSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) i = i + 1 - if int(self.cluster_value) > len(adata.uns['SCANPY_leiden_colors']): - Messagebox.show_error("Python Error", "Make sure gene name in dataset") + if int(self.cluster_value) > len(adata.uns["SCANPY_leiden_colors"]): + Messagebox.show_error( + "Python Error", "Make sure gene name in dataset" + ) else: - sc.pl.rank_genes_groups_heatmap(adata, groups=str(self.cluster_value), groupby="SCANPY_leiden", - show=False, save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/heatmapSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.rank_genes_groups_heatmap( + adata, + groups=str(self.cluster_value), + groupby="SCANPY_leiden", + show=False, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + + "/figures/heatmapSCANPY_" + + str(i) + + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) else: sc.pp.calculate_qc_metrics(adata, inplace=True) - sc.pl.spatial(adata, img_key="hires", color="log1p_total_counts", title='log1p_total_counts', - show=False, - spot_size=20, color_map=self.gene_color_type, save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.spatial( + adata, + img_key="hires", + color="log1p_total_counts", + title="log1p_total_counts", + show=False, + spot_size=20, + color_map=self.gene_color_type, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(adata, color="SCANPY_leiden", title='SCANPY-leiden-umap', show=False, s=6, save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.umap( + adata, + color="SCANPY_leiden", + title="SCANPY-leiden-umap", + show=False, + s=6, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) i = i + 1 - sc.pl.spatial(adata, color="SCANPY_leiden", title='SCANPY-leiden', show=False, save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.spatial( + adata, + color="SCANPY_leiden", + title="SCANPY-leiden", + show=False, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) i = i + 1 plt.rcParams["figure.figsize"] = (3, 3) - sc.pl.umap(adata, color="SCANPY_kmeans", title='SCANPY-kmeans-umap', show=False, s=6, - save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/umapSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.umap( + adata, + color="SCANPY_kmeans", + title="SCANPY-kmeans-umap", + show=False, + s=6, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/umapSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) i = i + 1 - sc.pl.spatial(adata, color="SCANPY_kmeans", title='SCANPY-kmeans', show=False, - save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/showSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') + sc.pl.spatial( + adata, + color="SCANPY_kmeans", + title="SCANPY-kmeans", + show=False, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + "/figures/showSCANPY_" + str(i) + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) i = i + 1 - if int(self.cluster_value) > len(adata.uns['SCANPY_leiden_colors']): - Messagebox.show_error("Python Error", "Make sure gene name in dataset") + if int(self.cluster_value) > len(adata.uns["SCANPY_leiden_colors"]): + Messagebox.show_error( + "Python Error", "Make sure gene name in dataset" + ) else: - sc.pl.rank_genes_groups_heatmap(adata, groups=str(self.cluster_value), groupby="SCANPY_leiden", - show=False, save='SCANPY_' + str(i) + '.png') - shutil.move(test_file_path + '/figures/heatmapSCANPY_' + str(i) + '.png', - path + '/SCANPY_' + str(i) + '.png') - print(f'Result images are saved in : {test_file_path}/figures') + sc.pl.rank_genes_groups_heatmap( + adata, + groups=str(self.cluster_value), + groupby="SCANPY_leiden", + show=False, + save="SCANPY_" + str(i) + ".png", + ) + shutil.move( + test_file_path + + "/figures/heatmapSCANPY_" + + str(i) + + ".png", + path + "/SCANPY_" + str(i) + ".png", + ) + print(f"Result images are saved in : {test_file_path}/figures") def scoller(): - self.figure_ybar = ttk.Scrollbar(self.figure_Frame, orient=VERTICAL, cursor='draft_small') + self.figure_ybar = ttk.Scrollbar( + self.figure_Frame, orient=VERTICAL, cursor="draft_small" + ) self.figure_ybar.pack(side=RIGHT, fill=Y) self.figure_ybar.config(command=self.canvas.yview) - self.figure_xbar = ttk.Scrollbar(self.figure_Frame, orient=HORIZONTAL, cursor='draft_small') + self.figure_xbar = ttk.Scrollbar( + self.figure_Frame, orient=HORIZONTAL, cursor="draft_small" + ) self.figure_xbar.pack(side=BOTTOM, fill=X) self.figure_xbar.config(command=self.canvas.xview) @@ -4770,35 +6812,40 @@ def scoller(): self.show_frame.bind("", onFrameconfigure) def onFrameconfigure(event): - self.canvas.configure(scrollregion=self.canvas.bbox("all"), width=1000, height=650) + self.canvas.configure( + scrollregion=self.canvas.bbox("all"), width=1000, height=650 + ) def choose_color(): colorvalue = colorchooser.askcolor() color_list = [] color = colorvalue[1] print(color) - color_lens = max(len(adata.uns['SCANPY_leiden_colors']), len(adata.uns['SCANPY_kmeans_colors'])) - if color[1:3] == 'ff': + color_lens = max( + len(adata.uns["SCANPY_leiden_colors"]), + len(adata.uns["SCANPY_kmeans_colors"]), + ) + if color[1:3] == "ff": color_list.append(color) list = random.sample(color_panel.FF_color, color_lens) color_list = color_list + list - elif color[1:3] == 'cc': + elif color[1:3] == "cc": color_list.append(color) list = random.sample(color_panel.CC_color, color_lens) color_list = color_list + list - elif color[1:3] == '99': + elif color[1:3] == "99": color_list.append(color) list = random.sample(color_panel.NN_color, color_lens) color_list = color_list + list - elif color[1:3] == '66': + elif color[1:3] == "66": color_list.append(color) list = random.sample(color_panel.SS_color, color_lens) color_list = color_list + list - elif color[1:3] == '33': + elif color[1:3] == "33": color_list.append(color) list = random.sample(color_panel.TT_color, color_lens) color_list = color_list + list - elif color[1:3] == '00': + elif color[1:3] == "00": color_list.append(color) list = random.sample(color_panel.ZZ_color, color_lens) color_list = color_list + list @@ -4809,24 +6856,38 @@ def choose_color(): print(color_list) if self.label_files_exit: - adata.uns['GroundTruth_colors'] = color_list[:len(adata.uns['GroundTruth_colors'])] - adata.uns['SCANPY_leiden_colors'] = color_list[:len(adata.uns['SCANPY_leiden_colors'])] - adata.uns['SCANPY_kmeans_colors'] = color_list[:len(adata.uns['SCANPY_kmeans_colors'])] + adata.uns["GroundTruth_colors"] = color_list[ + : len(adata.uns["GroundTruth_colors"]) + ] + adata.uns["SCANPY_leiden_colors"] = color_list[ + : len(adata.uns["SCANPY_leiden_colors"]) + ] + adata.uns["SCANPY_kmeans_colors"] = color_list[ + : len(adata.uns["SCANPY_kmeans_colors"]) + ] self.color_reset = color_list self.gene_color_type = color_panel.five_gene_color[random.randint(0, 5)] os.chdir(Raw_PATH) draw_images() - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + fig_path = ( + test_file_path + + "/figures/" + + self.method_flag + + "_" + + self.data_type + ) figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0) - fig_path = test_file_path + '/figures/' + self.method_flag + '_' + self.data_type + fig_path = ( + test_file_path + "/figures/" + self.method_flag + "_" + self.data_type + ) if not os.path.isdir(fig_path): os.mkdir(fig_path) @@ -4855,66 +6916,98 @@ def choose_color(): self.show_frame = ttk.Frame(self.canvas) scoller() - self.set_frame = ttk.Frame(self.figure_Frame, borderwidth=2, relief="sunken") - self.set_frame.pack(side='right', expand=YES, anchor=N) + self.set_frame = ttk.Frame( + self.figure_Frame, borderwidth=2, relief="sunken" + ) + self.set_frame.pack(side="right", expand=YES, anchor=N) self.set_frame_one = ttk.Frame(self.set_frame) self.set_frame_one.pack(side=TOP, expand=YES) self.set_frame_two = ttk.Frame(self.set_frame) self.set_frame_two.pack(side=TOP, expand=YES) - self.Reset = ttk.Button(self.set_frame_one, text='Reset all colors', command=choose_color, width=12) + self.Reset = ttk.Button( + self.set_frame_one, + text="Reset all colors", + command=choose_color, + width=12, + ) self.Reset.grid(row=0, column=0, sticky=W, pady=0, padx=0) - self.domain_color_label = ttk.Label(self.set_frame_one, text='Reset domain color: ', width=20) + self.domain_color_label = ttk.Label( + self.set_frame_one, text="Reset domain color: ", width=20 + ) self.domain_color_label.grid(row=1, column=0, sticky=W, pady=0) self.Reset_domain_color = ttk.Entry(self.set_frame_one, width=10) self.Reset_domain_color.grid(row=1, column=1, sticky=W, pady=0) - Tooltip(self.Reset_domain_color, "Input value must be int type and in [1:cluster_name]: 2") + Tooltip( + self.Reset_domain_color, + "Input value must be int type and in [1:cluster_name]: 2", + ) self.color_update = None def Reset_single_domain_color(): from tkinter import colorchooser + colorvalue = colorchooser.askcolor() color = colorvalue[1] print(color) cluster = self.Reset_domain_color.get() self.color_reset[int(cluster) - 1] = color - adata.uns['SCANPY_leiden_colors'] = self.color_reset[:len(adata.uns['SCANPY_leiden_colors'])] - adata.uns['SCANPY_kmeans_colors'] = self.color_reset[:len(adata.uns['SCANPY_kmeans_colors'])] + adata.uns["SCANPY_leiden_colors"] = self.color_reset[ + : len(adata.uns["SCANPY_leiden_colors"]) + ] + adata.uns["SCANPY_kmeans_colors"] = self.color_reset[ + : len(adata.uns["SCANPY_kmeans_colors"]) + ] draw_images() figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - img = Image.open(fig_path + '/' + figures[i]) + img = Image.open(fig_path + "/" + figures[i]) print(img.size) - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) - self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0, padx=0) + self.result_images.grid( + row=i // 3, column=i % 3, sticky=W, pady=0, padx=0 + ) s = i - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Confirm', - command=Reset_single_domain_color) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, + width=10, + text="Confirm", + command=Reset_single_domain_color, + ) self.Reset_domain_btn.grid(row=1, column=2, sticky=W, pady=10) - self.update_image_label = ttk.Label(self.set_frame_one, text='Reset image dpi: ', width=20) + self.update_image_label = ttk.Label( + self.set_frame_one, text="Reset image dpi: ", width=20 + ) self.update_image_label.grid(row=2, column=0, sticky=W, pady=10) self.update_image_scale = ttk.Entry(self.set_frame_one, width=10) self.update_image_scale.grid(row=2, column=1, sticky=W, pady=10) - Tooltip(self.update_image_scale, "Input value must be int type and >= 300: 300") + Tooltip( + self.update_image_scale, "Input value must be int type and >= 300: 300" + ) def ipdate_hd(): dpi = self.update_image_scale.get() print(dpi) import matplotlib.pyplot as plt + plt.rcParams["figure.figsize"] = (3, 3) sc.set_figure_params(dpi=dpi) draw_images() - self.Reset_domain_btn = ttk.Button(self.set_frame_one, width=10, text='Save', command=ipdate_hd) + self.Reset_domain_btn = ttk.Button( + self.set_frame_one, width=10, text="Save", command=ipdate_hd + ) self.Reset_domain_btn.grid(row=2, column=2, sticky=W, pady=0) - self.gene_visualization_label = ttk.Label(self.set_frame_one, text='Input gene name: ', width=20) + self.gene_visualization_label = ttk.Label( + self.set_frame_one, text="Input gene name: ", width=20 + ) self.gene_visualization_label.grid(row=3, column=0, sticky=W, pady=0) self.gene_visualization_entry = ttk.Entry(self.set_frame_one, width=10) @@ -4924,28 +7017,36 @@ def ipdate_hd(): def gene_visualization(): gene = self.gene_visualization_entry.get() if gene not in adata.var_names: - print(f'{gene} is mot in adata!!Please input right gene name!') - sc.pl.spatial(adata, img_key="hires", color=gene, title="$" + gene + "$", sopt_size=self.spot_size, show=False, - save=gene + '.png') + print(f"{gene} is mot in adata!!Please input right gene name!") + sc.pl.spatial( + adata, + img_key="hires", + color=gene, + title="$" + gene + "$", + sopt_size=self.spot_size, + show=False, + save=gene + ".png", + ) global img0 - photo = Image.open(test_file_path + '/figures/show' + gene + '.png') + photo = Image.open(test_file_path + "/figures/show" + gene + ".png") img0 = ImageTk.PhotoImage(photo) img1 = ttk.Label(self.set_frame_two, image=img0) img1.grid(row=0, column=0, sticky=W, pady=0) - if os.path.exists(test_file_path + '/figures/show' + gene + '.png'): - os.remove(test_file_path + '/figures/show' + gene + '.png') + if os.path.exists(test_file_path + "/figures/show" + gene + ".png"): + os.remove(test_file_path + "/figures/show" + gene + ".png") print("yes") else: print("error!") - self.gene_visualization_btn = ttk.Button(self.set_frame_one, width=10, command=gene_visualization, - text='Show') + self.gene_visualization_btn = ttk.Button( + self.set_frame_one, width=10, command=gene_visualization, text="Show" + ) self.gene_visualization_btn.grid(row=3, column=2, sticky=W, pady=0) figures = os.listdir(fig_path) global image_list image_list = [] for i in range(len(figures)): - image_list.append(ttk.PhotoImage(file=fig_path + '/' + figures[i])) + image_list.append(ttk.PhotoImage(file=fig_path + "/" + figures[i])) self.result_images = ttk.Label(self.show_frame, image=image_list[i]) self.result_images.grid(row=i // 3, column=i % 3, sticky=W, pady=0) s = i @@ -4956,21 +7057,28 @@ def gene_visualization(): def VIEW_3D(): import webbrowser + current_file_path = os.path.abspath(__file__) test_file_path = os.path.dirname(current_file_path) path = os.path.dirname(test_file_path) - data_save_path = running_path + '/module_3D_data/DLPFC' - self.web_Server_Thread(os.path.join(data_save_path, 'webcache'), int(self.Entry.get())) - http = 'http://127.0.0.1:' + self.Entry.get() + '/' + data_save_path = running_path + "/module_3D_data/DLPFC" + self.web_Server_Thread( + os.path.join(data_save_path, "webcache"), int(self.Entry.get()) + ) + http = "http://127.0.0.1:" + self.Entry.get() + "/" # 'http://127.0.0.1:8050/' webbrowser.open(http) os.chdir(Raw_PATH) - self.Reset = ttk.Button(self.set_frame_one, text='3D VIEW', command=VIEW_3D, width=10) + self.Reset = ttk.Button( + self.set_frame_one, text="3D VIEW", command=VIEW_3D, width=10 + ) self.Reset.grid(row=0, column=2, sticky=W, pady=0) self.result_queue.put(adata) else: - Messagebox.show_warning(title="Attention", message='Waiting for models training!!!') + Messagebox.show_warning( + title="Attention", message="Waiting for models training!!!" + ) def SCANPY_Data_Analysis(self): self.model_train_flag = False @@ -4979,26 +7087,33 @@ def SCANPY_Data_Analysis(self): adata_remove = self.result_queue.get() del adata_remove adata = self.result_queue.get() - if 'highly_variable' in adata.var.columns: - adata = adata[:, adata.var['highly_variable']] + if "highly_variable" in adata.var.columns: + adata = adata[:, adata.var["highly_variable"]] else: - sc.pp.highly_variable_genes(adata, flavor='seurat', n_top_genes=3000, inplace=True) - adata = adata[:, adata.var['highly_variable']] - if 'GroundTruth' in adata.obs.columns: + sc.pp.highly_variable_genes( + adata, flavor="seurat", n_top_genes=3000, inplace=True + ) + adata = adata[:, adata.var["highly_variable"]] + if "GroundTruth" in adata.obs.columns: self.label_files_exit = True - sc.pp.pca(adata, n_comps=int(self.rad_cutoff_value), use_highly_variable=True, svd_solver='arpack') - sc.pp.neighbors(adata, use_rep='X_pca') + sc.pp.pca( + adata, + n_comps=int(self.rad_cutoff_value), + use_highly_variable=True, + svd_solver="arpack", + ) + sc.pp.neighbors(adata, use_rep="X_pca") sc.tl.umap(adata) # self.result_queue.put(adata) adata.write_h5ad(os.path.join(running_path, "result", "SCANPY_output.h5ad")) self.pb.stop() - self.pb['value'] = 100 - self.setvar('prog-message', 'SCANPY run over!') - self.setvar('End-time', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + self.pb["value"] = 100 + self.setvar("prog-message", "SCANPY run over!") + self.setvar("End-time", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) EndTime = datetime.now().replace(microsecond=0) - self.setvar('total-time-cost', EndTime - self.StartTime) + self.setvar("total-time-cost", EndTime - self.StartTime) self.model_train_flag = True self.cluster_flag = True @@ -5009,109 +7124,173 @@ def SCANPY_Thread(self): def Data_process(self): self.StartTime = datetime.now().replace(microsecond=0) - self.setvar('prog-time-started', datetime.now().strftime("%Y-%m-%d %H:%M:%S")) - - self.setvar('current-file-msg', self.method_flag) - if self.method_flag == 'STAGATE': - self._value = 'Log: ' + self.method_flag + ' is running ,' \ - 'the visualization results are displayed below......' - self.setvar('scroll-message', self._value) + self.setvar("prog-time-started", datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + + self.setvar("current-file-msg", self.method_flag) + if self.method_flag == "STAGATE": + self._value = ( + "Log: " + self.method_flag + " is running ," + "the visualization results are displayed below......" + ) + self.setvar("scroll-message", self._value) self.pb.start() - self.setvar('prog-message', 'STAGATE is running!!') + self.setvar("prog-message", "STAGATE is running!!") self.label_files_exit = False self.STAGATE_Thread() - elif self.method_flag == 'STAligner': - self._value = 'Log: ' + self.method_flag + 'is running, the visualization results are displayed ' \ - 'below...... ' - self.setvar('scroll-message', self._value) + elif self.method_flag == "STAligner": + self._value = ( + "Log: " + + self.method_flag + + "is running, the visualization results are displayed " + "below...... " + ) + self.setvar("scroll-message", self._value) self.pb.start() - self.setvar('prog-message', 'STAligner is running!!') + self.setvar("prog-message", "STAligner is running!!") self.label_files_exit = False self.STAligner_Thread() - elif self.method_flag == 'STAMarker': - self._value = 'Log: ' + self.method_flag + 'is running, the visualization results are displayed ' \ - 'below...... ' - self.setvar('scroll-message', self._value) + elif self.method_flag == "STAMarker": + self._value = ( + "Log: " + + self.method_flag + + "is running, the visualization results are displayed " + "below...... " + ) + self.setvar("scroll-message", self._value) self.pb.start() - self.setvar('prog-message', 'STAMarker is running!!') + self.setvar("prog-message", "STAMarker is running!!") self.STAMarker_Thread_two() - elif self.method_flag == 'STAGE': - self._value = 'Log: ' + self.method_flag + ' is running ,' \ - 'the visualization results are displayed below......' - self.setvar('scroll-message', self._value) - if self.data_type not in ['10x', 'ST', 'Slide-seq']: - self.data_type = '10x' + elif self.method_flag == "STAGE": + self._value = ( + "Log: " + self.method_flag + " is running ," + "the visualization results are displayed below......" + ) + self.setvar("scroll-message", self._value) + if self.data_type not in ["10x", "ST", "Slide-seq"]: + self.data_type = "10x" self.pb.start() - self.setvar('prog-message', 'STAGE is running!!') + self.setvar("prog-message", "STAGE is running!!") self.STAGE_Thread() - elif self.method_flag == 'SpaGCN': + elif self.method_flag == "SpaGCN": self.label_files_exit = False - self._value = 'Log: ' + self.method_flag + ' is running ,' \ - 'the visualization results are displayed below......' - self.setvar('scroll-message', self._value) + self._value = ( + "Log: " + self.method_flag + " is running ," + "the visualization results are displayed below......" + ) + self.setvar("scroll-message", self._value) self.pb.start() - self.setvar('prog-message', 'SpaGCN is running!!') + self.setvar("prog-message", "SpaGCN is running!!") self.SpaGCN_Thread() - elif self.method_flag == 'SEDR': + elif self.method_flag == "SEDR": self.label_files_exit = False - self._value = 'Log: ' + self.method_flag + ' is running ,' \ - 'the visualization results are displayed below......' - self.setvar('scroll-message', self._value) + self._value = ( + "Log: " + self.method_flag + " is running ," + "the visualization results are displayed below......" + ) + self.setvar("scroll-message", self._value) self.pb.start() - self.setvar('prog-message', 'SEDR is running!!') + self.setvar("prog-message", "SEDR is running!!") self.SEDR_Thread() - elif self.method_flag == 'SCANPY': + elif self.method_flag == "SCANPY": self.label_files_exit = False - self._value = 'Log: ' + self.method_flag + ' is running ,' \ - 'the visualization results are displayed below......' - self.setvar('scroll-message', self._value) + self._value = ( + "Log: " + self.method_flag + " is running ," + "the visualization results are displayed below......" + ) + self.setvar("scroll-message", self._value) self.pb.start() - self.setvar('prog-message', 'SCANPY is running!!') + self.setvar("prog-message", "SCANPY is running!!") self.SCANPY_Thread() else: - Messagebox.show_error('Other methods should be used by STABox packages!', 'Warning!') - + Messagebox.show_error( + "Other methods should be used by STABox packages!", "Warning!" + ) def settings(self): - settingbox = ttk.Toplevel(title='settings') - settingbox.geometry('300x100+100+100') + settingbox = ttk.Toplevel(title="settings") + + # 获取父窗口大小以计算居中位置 + parent_width = self.master.winfo_width() + parent_height = self.master.winfo_height() + # 计算居中的X和Y偏移量 + x_offset = (parent_width - 300) // 2 + y_offset = (parent_height - 100) // 2 + # 设置窗口的几何属性,使其居中 + settingbox.geometry("300x100+{}+{}".format(x_offset, y_offset)) settingbox.lift() - ttk.Label(settingbox, text='R_HOME').grid(row=0, sticky="w") - ttk.Label(settingbox, text='R_USER').grid(row=1, sticky="w") - R_HOME_box = ttk.Entry(settingbox, textvariable='R_HOME', validate="focusout", width=30) + + # 创建设置表单 + ttk.Label(settingbox, text="R_HOME").grid(row=0, column=0, sticky="w") + ttk.Label(settingbox, text="R_USER").grid(row=1, column=0, sticky="w") + + R_HOME_var = tk.StringVar() + R_USER_var = tk.StringVar() + R_HOME_box = ttk.Entry( + settingbox, textvariable=R_HOME_var, validate="focusout", width=30 + ) R_HOME_box.grid(row=0, column=1) - R_USER_box = ttk.Entry(settingbox, textvariable='R_USER', validate="focusout", width=30) + R_USER_box = ttk.Entry( + settingbox, textvariable=R_USER_var, validate="focusout", width=30 + ) R_USER_box.grid(row=1, column=1) def load_setting(): - path = '../Renv_setting.yaml' + path = "../Renv_setting.yaml" if os.path.exists(path): - with open(path, 'r') as f: - yamlData = yaml.safe_load(f) - os.environ['R_HOME'] = yamlData['R_HOME'] - os.environ['R_USER'] = yamlData['R_USER'] - self.setvar('R_HOME', yamlData['R_HOME']) - self.setvar('R_USER', yamlData['R_USER']) - settingbox.destroy() + with open(path, "r") as f: + yaml_data = yaml.safe_load(f) + os.environ["R_HOME"] = yaml_data["R_HOME"] + os.environ["R_USER"] = yaml_data["R_USER"] + R_HOME_var.set(yaml_data.get("R_HOME", "")) + R_USER_var.set(yaml_data.get("R_USER", "")) + + # 延时1200毫秒后显示信息框 + settingbox.after( + 1200, + lambda: ( + messagebox.showinfo( + "Settings Loaded", + f"R_HOME has been set to: \n {R_HOME_var.get()} \nR_USER has been set to: {R_USER_var.get()}", + ), + settingbox.destroy(), + ), + ) else: - Messagebox.show_error('Make sure yaml exist!', 'Error!') + messagebox.showerror("Error", "Make sure the YAML file exists!") settingbox.destroy() - load_setting_button = ttk.Button(settingbox, text="Load yaml", width=9, command=load_setting) - load_setting_button.grid(row=2, column=0) + def save_data(): + # 验证输入 + if not R_HOME_var.get() or not R_USER_var.get(): + messagebox.showwarning( + "Input Error", "R_HOME and R_USER cannot be empty. Please fill in both fields." + ) + return + + os.environ["R_HOME"] = R_HOME_var.get() + os.environ["R_USER"] = R_USER_var.get() - def get_data(): - os.environ['R_HOME'] = R_HOME_box.get() - os.environ['R_USER'] = R_USER_box.get() - setting = {"R_HOME": R_HOME_box.get(), - "R_USER": R_USER_box.get()} - with open('../Renv_setting.yaml', "w") as f: + setting = {"R_HOME": R_HOME_var.get(), "R_USER": R_USER_var.get()} + with open("../Renv_setting.yaml", "w") as f: yaml.dump(setting, f) - settingbox.destroy() - - check_button = ttk.Button(settingbox, text="Confirm", width=8, command=get_data) - check_button.grid(row=2, column=1) + # 延时1200毫秒后显示信息框 + settingbox.after( + 1200, + lambda: ( + messagebox.showinfo( + "Settings saved", "Save Renv-seting.yaml file successfully" + ), + settingbox.destroy(), + ), + ) + + load_button = ttk.Button( + settingbox, text="Load yaml", width=9, command=load_setting + ) + load_button.grid(row=2, column=0) + save_button = ttk.Button(settingbox, text="Confirm", width=8, command=save_data) + save_button.grid(row=2, column=1) class CollapsingFrame(ttk.Frame): @@ -5124,8 +7303,8 @@ def __init__(self, master, **kwargs): # widget images self.images = [ - ttk.PhotoImage(file=PATH / 'icons8_double_up_24px.png'), - ttk.PhotoImage(file=PATH / 'icons8_double_right_24px.png') + ttk.PhotoImage(file=PATH / "icons8_double_up_24px.png"), + ttk.PhotoImage(file=PATH / "icons8_double_right_24px.png"), ] def add(self, child, title="", bootstyle=PRIMARY, **kwargs): @@ -5145,7 +7324,7 @@ def add(self, child, title="", bootstyle=PRIMARY, **kwargs): **kwargs (Dict): Other optional keyword arguments. """ - if child.winfo_class() != 'TFrame': + if child.winfo_class() != "TFrame": return style_color = Bootstyle.ttkstyle_widget_color(bootstyle) @@ -5153,13 +7332,9 @@ def add(self, child, title="", bootstyle=PRIMARY, **kwargs): frm.grid(row=self.cumulative_rows, column=0, sticky=EW) # header title - header = ttk.Label( - master=frm, - text=title, - bootstyle=(style_color, INVERSE) - ) - if kwargs.get('textvariable'): - header.configure(textvariable=kwargs.get('textvariable')) + header = ttk.Label(master=frm, text=title, bootstyle=(style_color, INVERSE)) + if kwargs.get("textvariable"): + header.configure(textvariable=kwargs.get("textvariable")) header.pack(side=LEFT, fill=BOTH, padx=10) # header toggle button @@ -5171,7 +7346,7 @@ def _func(c=child): image=self.images[0], bootstyle=style_color, # 注意这边 - command=_func + command=_func, ) btn.pack(side=RIGHT) @@ -5206,11 +7381,11 @@ def __init__(self, text_widget, max_lines): self.current_lines = 0 def write(self, message): - lines = message.strip().split('\n') + lines = message.strip().split("\n") for line in lines: if self.current_lines >= self.max_lines: break - self.text_widget.insert(tk.END, line + '\n') + self.text_widget.insert(tk.END, line + "\n") self.current_lines += 1 self.text_widget.see(tk.END) diff --git a/requirement.txt b/requirement.txt index 6c811e0..f13c513 100644 --- a/requirement.txt +++ b/requirement.txt @@ -1,29 +1,129 @@ -ttkbootstrap==1.9.0 -opencv-python==4.8.0.74 -numpy==1.20.3 -anndata==0.7.8 -pandas==1.2.3 -scipy==1.5.3 -matplotlib==3.5.1 -scanpy==1.9.1 -umap-learn==0.5.2 -rpy2==2.9.5 -seaborn==0.11.2 -networkx==2.8.4 -hnswlib==0.5.1 -annoy==1.17.0 -tqdm==4.64.1 -torch==1.9.1 -torch-geometric==2.0.3 -torch-cluster==1.5.9 -torch-scatter==2.0.9 -torch-sparse==0.6.12 -PyYAML==6.0 -scikit-misc==0.1.4 -upsetplot==0.8.0 -Pillow==9.2.0 -mock==4.0.3 -louvain==0.8.0 -progress==1.6 +aiohappyeyeballs==2.4.0 +aiohttp==3.10.6 +aiosignal==1.3.1 +anndata==0.10.9 +annotated-types==0.7.0 +annoy==1.17.3 +array_api_compat==1.8 +asttokens @ file:///home/conda/feedstock_root/build_artifacts/asttokens_1698341106958/work +async-timeout==4.0.3 +attrs==24.2.0 +certifi==2024.8.30 +cffi==1.17.1 +charset-normalizer==3.3.2 +comm @ file:///home/conda/feedstock_root/build_artifacts/comm_1710320294760/work +contourpy==1.3.0 +cycler==0.12.1 +debugpy @ file:///croot/debugpy_1690905042057/work +decorator @ file:///home/conda/feedstock_root/build_artifacts/decorator_1641555617451/work +dgl==2.4.0+cu121 +entrypoints @ file:///home/conda/feedstock_root/build_artifacts/entrypoints_1643888246732/work +exceptiongroup @ file:///home/conda/feedstock_root/build_artifacts/exceptiongroup_1720869315914/work +executing @ file:///home/conda/feedstock_root/build_artifacts/executing_1725214404607/work +filelock==3.16.1 +fonttools==4.54.1 +frozenlist==1.4.1 +fsspec==2024.9.0 +gseapy==1.1.3 +h5py==3.11.0 +hnswlib==0.8.0 +idna==3.10 +igraph==0.11.6 intervaltree==3.1.0 -gseapy +ipykernel @ file:///home/conda/feedstock_root/build_artifacts/ipykernel_1719845459717/work +ipython @ file:///home/conda/feedstock_root/build_artifacts/ipython_1725050136642/work +jedi @ file:///home/conda/feedstock_root/build_artifacts/jedi_1696326070614/work +Jinja2==3.1.4 +joblib==1.4.2 +jupyter-client @ file:///home/conda/feedstock_root/build_artifacts/jupyter_client_1654730843242/work +jupyter_core @ file:///home/conda/feedstock_root/build_artifacts/jupyter_core_1727163409502/work +kiwisolver==1.4.7 +legacy-api-wrap==1.4 +leidenalg==0.10.2 +llvmlite==0.43.0 +louvain==0.8.2 +MarkupSafe==2.1.5 +matplotlib==3.9.2 +matplotlib-inline @ file:///home/conda/feedstock_root/build_artifacts/matplotlib-inline_1713250518406/work +mpmath==1.3.0 +multidict==6.1.0 +natsort==8.4.0 +nest_asyncio @ file:///home/conda/feedstock_root/build_artifacts/nest-asyncio_1705850609492/work +networkx==3.3 +numba==0.60.0 +numpy==2.0.2 +nvidia-cublas-cu12==12.1.3.1 +nvidia-cuda-cupti-cu12==12.1.105 +nvidia-cuda-nvrtc-cu12==12.1.105 +nvidia-cuda-runtime-cu12==12.1.105 +nvidia-cudnn-cu12==9.1.0.70 +nvidia-cufft-cu12==11.0.2.54 +nvidia-curand-cu12==10.3.2.106 +nvidia-cusolver-cu12==11.4.5.107 +nvidia-cusparse-cu12==12.1.0.106 +nvidia-nccl-cu12==2.20.5 +nvidia-nvjitlink-cu12==12.6.68 +nvidia-nvtx-cu12==12.1.105 +opencv-python==4.10.0.84 +packaging @ file:///home/conda/feedstock_root/build_artifacts/packaging_1718189413536/work +pandas==2.2.3 +parso @ file:///home/conda/feedstock_root/build_artifacts/parso_1712320355065/work +patsy==0.5.6 +pexpect @ file:///home/conda/feedstock_root/build_artifacts/pexpect_1706113125309/work +pickleshare @ file:///home/conda/feedstock_root/build_artifacts/pickleshare_1602536217715/work +pillow==10.4.0 +platformdirs @ file:///home/conda/feedstock_root/build_artifacts/platformdirs_1726613481435/work +POT==0.9.4 +progress==1.6 +prompt_toolkit @ file:///home/conda/feedstock_root/build_artifacts/prompt-toolkit_1718047967974/work +psutil @ file:///opt/conda/conda-bld/psutil_1656431268089/work +ptyprocess @ file:///home/conda/feedstock_root/build_artifacts/ptyprocess_1609419310487/work/dist/ptyprocess-0.7.0-py2.py3-none-any.whl +pure_eval @ file:///home/conda/feedstock_root/build_artifacts/pure_eval_1721585709575/work +pycparser==2.22 +pydantic==2.9.2 +pydantic_core==2.23.4 +pyg-lib==0.4.0+pt24cu121 +Pygments @ file:///home/conda/feedstock_root/build_artifacts/pygments_1714846767233/work +pynndescent==0.5.13 +pyparsing==3.1.4 +python-dateutil @ file:///home/conda/feedstock_root/build_artifacts/python-dateutil_1709299778482/work +pytz==2024.2 +PyYAML==6.0.2 +pyzmq @ file:///croot/pyzmq_1705605076900/work +requests==2.32.3 +rpy2==3.5.16 +scanpy==1.10.3 +scikit-learn==1.5.2 +scikit-misc==0.4.0 +scipy==1.14.1 +seaborn==0.13.2 +session_info==1.0.0 +six @ file:///home/conda/feedstock_root/build_artifacts/six_1620240208055/work +sortedcontainers==2.4.0 +stack-data @ file:///home/conda/feedstock_root/build_artifacts/stack_data_1669632077133/work +statsmodels==0.14.3 +stdlib-list==0.10.0 +sympy==1.13.3 +texttable==1.7.0 +threadpoolctl==3.5.0 +torch==2.4.0 +torch-geometric==2.6.0 +torch_cluster==1.6.3+pt24cu121 +torch_scatter==2.1.2+pt24cu121 +torch_sparse==0.6.18+pt24cu121 +torch_spline_conv==1.2.2+pt24cu121 +torchaudio==2.4.1 +torchvision==0.19.1 +tornado @ file:///home/conda/feedstock_root/build_artifacts/tornado_1648827254365/work +tqdm==4.66.5 +traitlets @ file:///home/conda/feedstock_root/build_artifacts/traitlets_1713535121073/work +triton==3.0.0 +ttkbootstrap==1.10.1 +typing_extensions @ file:///home/conda/feedstock_root/build_artifacts/typing_extensions_1717802530399/work +tzdata==2024.2 +tzlocal==5.2 +umap-learn==0.5.6 +UpSetPlot==0.9.0 +urllib3==2.2.3 +wcwidth @ file:///home/conda/feedstock_root/build_artifacts/wcwidth_1704731205417/work +yarl==1.12.1 \ No newline at end of file