CHAOS Visualization of the Mouse Spleen Dataset
Loading Packages
[1]:
import warnings
warnings.filterwarnings('ignore')
import scanpy as sc
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.path.append('../Mouse_Spleen/')
sys.path.append('../../../')
from SpatialCOC.utils import calculate_chaos
Loading Data
[2]:
slices = ['1', '2'] ## 1, 2
# List of methods
methods = ['SpatialCOC', 'COSMOS', 'SpatialGlue', 'Seurat', 'MultiVI', 'MultiMAP', 'STAGATE', 'SpaGCN', 'Modality1', 'Modality2']
# Create a dictionary to store data for each slice
adata_results = {}
# Load data and store it
for slice_name in slices:
path = f'../../Mouse_Spleen_Replicate{slice_name}.h5ad'
result = sc.read_h5ad(path)
adata_results[slice_name] = {
'adata': result,
'chaos_scores': {}
}
Calculating CHAOS
[3]:
for slice_name, data in adata_results.items():
adata = data['adata'] # Assume data is an AnnData object
spatial_coords = adata.obsm['spatial'] # Retrieve spatial coordinates
for method in adata.obs.columns: # Iterate over each method
labels = adata.obs[method].values # Retrieve clustering labels
chaos_values = calculate_chaos(spatial_coords, labels) # Calculate CHAOS scores
data['chaos_scores'][method] = chaos_values # Store CHAOS scores
[9]:
import pandas as pd
import numpy as np
# 创建一个字典来存储所有结果
all_results = {}
# 遍历每个切片
for slice_name, data in adata_results.items():
adata = data['adata']
spatial_coords = adata.obsm['spatial']
slice_chaos_results = {}
for method in adata.obs.columns:
labels = adata.obs[method].values
chaos_values = calculate_chaos(spatial_coords, labels)
data['chaos_scores'][method] = chaos_values
# 确保转换为Python float列表,而不是numpy数组
if isinstance(chaos_values, (list, np.ndarray)):
slice_chaos_results[method] = [float(v) for v in chaos_values]
else:
slice_chaos_results[method] = [float(chaos_values)]
all_results[slice_name] = slice_chaos_results
# 保存到Excel
output_path = 'chaos_results.xlsx'
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
for slice_name, chaos_results in all_results.items():
# 转换为DataFrame:方法为行,每个CHAOS值为列
df = pd.DataFrame.from_dict(chaos_results, orient='index')
# 重命名列为 CHAOS_1, CHAOS_2, ...
df.columns = [f'CHAOS_{i+1}' for i in df.columns]
df.index.name = 'Method'
df = df.reset_index()
sheet_name = str(slice_name)[:31]
df.to_excel(writer, sheet_name=sheet_name, index=False)
print(f"Sheet '{sheet_name}' created with {len(df)} methods")
print(f"\nResults saved to: {output_path}")
Sheet '1' created with 10 methods
Sheet '2' created with 10 methods
Results saved to: chaos_results.xlsx
Ploting
[ ]:
# Define methods and corresponding colors
methods = ['SpatialCOC', 'COSMOS','SpatialGlue', 'Seurat', 'MultiVI', 'MultiMAP', 'STAGATE', 'SpaGCN']
colors = ['#D0836F', '#df871b', '#E4BE64', '#94aebd', '#87AC9A', '#9B8169', '#8D8E99', '#F5ECBA']
# Set global font size and font
fontsize = 20
plt.rcParams['font.sans-serif'] = ['Arial']
plt.rcParams['font.size'] = fontsize
# Iterate through each slice
for slice_name in slices:
# Get the CHAOS score data for the current slice
chaos_scores = adata_results[slice_name]['chaos_scores']
# Prepare data: CHAOS scores for each method
data = [chaos_scores[method] for method in methods]
# Calculate the medians of Modality1 and Modality2 separately
median_modality1 = np.median(data[0]) # Median of Modality1
median_modality2 = np.median(data[1]) # Median of Modality2
# Determine the best performance between the two medians
max_median = min(median_modality1, median_modality2)
# Automatically calculate the y-axis range
all_scores = np.concatenate(data) # Combine all data into one array
y_min = np.min(all_scores) - 0.05 * (np.max(all_scores) - np.min(all_scores)) # Slightly less than the minimum value
y_max = np.max(all_scores) + 0.05 * (np.max(all_scores) - np.min(all_scores)) # Slightly more than the maximum value
# Create a new figure
plt.figure(figsize=(5, 5))
# Draw the boxplot
bp = plt.boxplot(data, patch_artist=True,
boxprops=dict(linestyle='-', linewidth=1, edgecolor='black'), # Box edges
medianprops=dict(linestyle='-', linewidth=1, color='black'), # Median line
whiskerprops=dict(linestyle='-', linewidth=1, color='black'), # Whiskers
capprops=dict(linestyle='-', linewidth=1, color='black'), # Caps
widths=0.85, # Box width
showfliers=False) # Do not show outliers
# Color the boxes
for patch, color in zip(bp['boxes'], colors):
patch.set_facecolor(color)
# Remove x-axis tick labels
plt.xticks([]) # Remove x-axis tick labels
# Set the unified y-axis range
y_max = 2.6 if slice_name == '1' else 3
plt.ylim(y_min, y_max)
# Add y-axis label
plt.ylabel('CHAOS Score', fontsize=fontsize)
# Thicken the plot's border
for spine in plt.gca().spines.values():
spine.set_linewidth(2)
# Add grid lines
plt.grid(axis='y', color='gray', linestyle='--', alpha=1, zorder=-10, linewidth=1.5)
# Add vertical dashed lines
for x in range(1, len(methods) + 1):
plt.axvline(x=x, color='gray', linestyle='--', alpha=1, zorder=-10, linewidth=1.5)
# Draw a horizontal line to represent the best median performance
plt.axhline(y=max_median, color='red', linestyle='--', linewidth=2)
# Print plotting information
print(f"Drawing plot for {slice_name} - CHAOS Score")
plt.tight_layout(pad=0.1, rect=[0.03, 0, 1, 0.98])
# Save the image
save_path = f"./replicate{slice_name}/"
plt.savefig(save_path + f"CHAOS_Score.png", dpi=500)
plt.savefig(save_path + f"CHAOS_Score.eps")
plt.show()
Drawing plot for 1 - CHAOS Score
Drawing plot for 2 - CHAOS Score