H5ad generation
This commit is contained in:
parent
e157a17d69
commit
b39288fb9f
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*_marker_genes.txt
|
||||
*_scaled.csv
|
||||
BIN
embryo-backend/Data/CS11.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS11.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS12.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS12.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS13.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS13.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS14.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS14.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS15.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS15.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS16.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS16.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS17.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS17.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS18.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS18.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS20.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS20.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS21.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS21.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS22.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS22.h5ad
(Stored with Git LFS)
Binary file not shown.
BIN
embryo-backend/Data/CS23.h5ad
(Stored with Git LFS)
BIN
embryo-backend/Data/CS23.h5ad
(Stored with Git LFS)
Binary file not shown.
@ -19,7 +19,7 @@ assert os.path.exists(gene_list_file), f"❌ 缺少基因名文件 {gene_list_fi
|
||||
all_gene_names = pd.read_csv(gene_list_file, header=None)[0].tolist()
|
||||
gene_names = all_gene_names[:n_genes]
|
||||
|
||||
# ==== 真实 marker 基因 ====
|
||||
# ==== marker 基因 ====
|
||||
true_markers = {
|
||||
"Ectoderm": ["SOX2", "PAX6", "NES", "TUBB3", "OTX2"],
|
||||
"Mesoderm": ["TBXT", "MESP1", "HAND1", "GATA4", "PDGFRA"],
|
||||
@ -30,6 +30,7 @@ true_markers = {
|
||||
|
||||
# ==== 采样函数 ====
|
||||
def sample_mesh(mesh, label, n_samples):
|
||||
"""采样点云 + 颜色 + 标签"""
|
||||
if use_surface_sampling:
|
||||
points, face_idx = trimesh.sample.sample_surface(mesh, n_samples)
|
||||
if hasattr(mesh.visual, "vertex_colors") and len(mesh.visual.vertex_colors) == len(mesh.vertices):
|
||||
@ -63,7 +64,7 @@ for glb_name in glb_files:
|
||||
scene = trimesh.load(glb_path)
|
||||
if isinstance(scene, trimesh.Scene):
|
||||
for geom in scene.geometry.values():
|
||||
all_bounds.append(geom.bounds) # (min,max)
|
||||
all_bounds.append(geom.bounds)
|
||||
else:
|
||||
all_bounds.append(scene.bounds)
|
||||
|
||||
@ -73,7 +74,7 @@ global_max = np.max(all_bounds[:,1,:], axis=0)
|
||||
global_size = np.max(global_max - global_min)
|
||||
print(f"🌍 统一缩放基准: global_size={global_size}")
|
||||
|
||||
# ==== Step 2: 处理单个 GLB ====
|
||||
# ==== Step 2: 处理单个 GLB(应用全局变换) ====
|
||||
def process_glb(glb_path, sample_name):
|
||||
scene = trimesh.load(glb_path)
|
||||
all_points, all_colors, all_labels = [], [], []
|
||||
@ -83,7 +84,21 @@ def process_glb(glb_path, sample_name):
|
||||
for name, geom in scene.geometry.items():
|
||||
ratio = len(geom.vertices) / total_points
|
||||
n_samples = max(1, int(N_total * ratio))
|
||||
p, c, l = sample_mesh(geom, name, n_samples)
|
||||
|
||||
# ✅ 保护性获取变换矩阵
|
||||
try:
|
||||
transform = scene.graph.get(name)[0]
|
||||
except Exception:
|
||||
print(f"⚠️ {sample_name}: 子网格 {name} 没有变换路径,使用单位矩阵")
|
||||
transform = np.eye(4)
|
||||
|
||||
# ✅ 应用全局变换
|
||||
verts_world = trimesh.transform_points(geom.vertices, transform)
|
||||
|
||||
# ✅ 生成全局 mesh 进行采样
|
||||
mesh_world = trimesh.Trimesh(vertices=verts_world, faces=geom.faces, process=False)
|
||||
p, c, l = sample_mesh(mesh_world, name, n_samples)
|
||||
|
||||
all_points.append(p)
|
||||
all_colors.append(c)
|
||||
all_labels.append(l)
|
||||
@ -101,26 +116,21 @@ def process_glb(glb_path, sample_name):
|
||||
idx = np.random.choice(len(points), N_total, replace=False)
|
||||
points, colors, labels = points[idx], colors[idx], labels[idx]
|
||||
|
||||
# ✅ 平移到中心点
|
||||
# ✅ 一次性中心化 + 统一缩放
|
||||
center = points.mean(axis=0)
|
||||
points_centered = points - center
|
||||
|
||||
# ✅ 统一缩放(保持原始比例)
|
||||
points_scaled = points_centered / global_size
|
||||
|
||||
# ✅ 如需修正坐标系方向,可启用以下行(示例:交换Y和Z)
|
||||
# points_scaled = points_scaled[:, [0, 2, 1]]
|
||||
# points_scaled[:, 1] *= -1
|
||||
|
||||
df = pd.DataFrame(points_scaled, columns=["x","y","z"])
|
||||
df["r"], df["g"], df["b"] = colors[:,0], colors[:,1], colors[:,2]
|
||||
df["label"] = labels
|
||||
|
||||
csv_file = os.path.join(script_dir, f"{sample_name}_point_cloud_30000_centered_scaled.csv")
|
||||
df.to_csv(csv_file, index=False)
|
||||
print(f"✅ 已导出 {csv_file} (中心化 & 统一大小, 保持比例)")
|
||||
print(f"✅ 已导出 {csv_file} (修正组织错位, 中心化 & 统一比例)")
|
||||
return df
|
||||
|
||||
|
||||
# ==== Step 3: 生成 h5ad ====
|
||||
def create_h5ad(df, sample_name):
|
||||
points = df[['x','y','z']].to_numpy()
|
||||
|
||||
@ -9,4 +9,5 @@ dependencies = [
|
||||
"flask>=3.1.1",
|
||||
"flask-cors>=6.0.1",
|
||||
"pandas>=2.3.1",
|
||||
"trimesh>=4.7.1",
|
||||
]
|
||||
|
||||
14
uv.lock
14
uv.lock
@ -100,6 +100,7 @@ dependencies = [
|
||||
{ name = "flask" },
|
||||
{ name = "flask-cors" },
|
||||
{ name = "pandas" },
|
||||
{ name = "trimesh" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
@ -108,6 +109,7 @@ requires-dist = [
|
||||
{ name = "flask", specifier = ">=3.1.1" },
|
||||
{ name = "flask-cors", specifier = ">=6.0.1" },
|
||||
{ name = "pandas", specifier = ">=2.3.1" },
|
||||
{ name = "trimesh", specifier = ">=4.7.1" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -421,6 +423,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trimesh"
|
||||
version = "4.7.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/95/05/50656189ebd0563b2130ddd9b609b1db99eb241687dac0d2585882c35c33/trimesh-4.7.1.tar.gz", hash = "sha256:3863c2b2281fc7a99bf0b5de4a0011229bde4663babc0c1b53a1f855149ec898", size = 800778, upload-time = "2025-07-16T20:24:50.248Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/64/99e785dd4bb5796881b5686b0869a6ebf75b1b7d00932af577eb343c4f72/trimesh-4.7.1-py3-none-any.whl", hash = "sha256:338c938ae78ad5b4d08dd6ceaa739498a47627bf0073147ee9a384ddd7435267", size = 709034, upload-time = "2025-07-16T20:24:47.256Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.14.1"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user