From 67e7da82f07d2e97747d147b5d2b17079d0a8879 Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Tue, 12 Dec 2023 11:41:56 +0100 Subject: [PATCH 01/14] Create Spatial_mgcn.py --- method/Spatial_mgcn.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 method/Spatial_mgcn.py diff --git a/method/Spatial_mgcn.py b/method/Spatial_mgcn.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/method/Spatial_mgcn.py @@ -0,0 +1 @@ + From 7e397a4524b77df454ef88d2e5f5d22c56392dab Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Tue, 12 Dec 2023 11:48:44 +0100 Subject: [PATCH 02/14] Create method.py --- method/Spatial_mgcn/method.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 method/Spatial_mgcn/method.py diff --git a/method/Spatial_mgcn/method.py b/method/Spatial_mgcn/method.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/method/Spatial_mgcn/method.py @@ -0,0 +1 @@ + From 0f51175efef0f2cae64fe7ef49ae84e1ce98618d Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Tue, 12 Dec 2023 11:50:43 +0100 Subject: [PATCH 03/14] Rename method/Spatial_mgcn.py to method/Spatial_mgcn/Spatial_mgcn.py --- method/{ => Spatial_mgcn}/Spatial_mgcn.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename method/{ => Spatial_mgcn}/Spatial_mgcn.py (100%) diff --git a/method/Spatial_mgcn.py b/method/Spatial_mgcn/Spatial_mgcn.py similarity index 100% rename from method/Spatial_mgcn.py rename to method/Spatial_mgcn/Spatial_mgcn.py From 41c89c440b9034a2b07e1d36725bf4b53fc7131a Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Tue, 12 Dec 2023 11:51:30 +0100 Subject: [PATCH 04/14] Delete method/Spatial_mgcn/method.py --- method/Spatial_mgcn/method.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 method/Spatial_mgcn/method.py diff --git a/method/Spatial_mgcn/method.py b/method/Spatial_mgcn/method.py deleted file mode 100644 index 8b137891..00000000 --- a/method/Spatial_mgcn/method.py +++ /dev/null @@ -1 +0,0 @@ - From 99e433687cfafbda486553eeb8f5d935e3e7cba3 Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Tue, 12 Dec 2023 11:52:05 +0100 Subject: [PATCH 05/14] Create Spatial_mgcn.yml --- method/Spatial_mgcn/Spatial_mgcn.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 method/Spatial_mgcn/Spatial_mgcn.yml diff --git a/method/Spatial_mgcn/Spatial_mgcn.yml b/method/Spatial_mgcn/Spatial_mgcn.yml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/method/Spatial_mgcn/Spatial_mgcn.yml @@ -0,0 +1 @@ + From e7e11b040acb6aefe6d42edd0e8f32b8b6a1a53c Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Tue, 12 Dec 2023 11:52:39 +0100 Subject: [PATCH 06/14] Update Spatial_mgcn.py --- method/Spatial_mgcn/Spatial_mgcn.py | 215 ++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) diff --git a/method/Spatial_mgcn/Spatial_mgcn.py b/method/Spatial_mgcn/Spatial_mgcn.py index 8b137891..3be2a5c9 100644 --- a/method/Spatial_mgcn/Spatial_mgcn.py +++ b/method/Spatial_mgcn/Spatial_mgcn.py @@ -1 +1,216 @@ +#!/usr/bin/env python +# Author_and_contribution: Niklas Mueller-Boetticher; created script + +import argparse + +parser = argparse.ArgumentParser( + description="""SpaGCN (https://www.nature.com/articles/s41592-021-01255-8) +Requirements: Visium or ST. Images can be used.""" +) + +parser.add_argument( + "-c", "--coordinates", help="Path to coordinates (as tsv).", required=True +) +parser.add_argument( + "-m", "--matrix", help="Path to (transformed) counts (as mtx).", required=False +) +parser.add_argument( + "-f", "--features", help="Path to features (as tsv).", required=True +) +parser.add_argument( + "-o", "--observations", help="Path to observations (as tsv).", required=True +) +parser.add_argument( + "-n", + "--neighbors", + help="Path to neighbor definitions. Square matrix (not necessarily symmetric) where each row contains the neighbors of this observation (as mtx).", + required=False, +) +parser.add_argument("-d", "--out_dir", help="Output directory.", required=True) +parser.add_argument( + "--dim_red", + help="Reduced dimensionality representation (e.g. PCA).", + required=False, +) +parser.add_argument("--image", help="Path to H&E staining.", required=False) +parser.add_argument( + "--n_clusters", help="Number of clusters to return.", required=True, type=int +) +parser.add_argument( + "--technology", + help="The technology of the dataset (Visium, ST, ...).", + required=True, +) +parser.add_argument( + "--seed", help="Seed to use for random operations.", required=True, type=int +) +parser.add_argument( + "--config", + help="Optional config file used to pass additional parameters.", + required=False, +) + +args = parser.parse_args() + +from pathlib import Path + +out_dir = Path(args.out_dir) + +# Output files +label_file = out_dir / "domains.tsv" +embedding_file = out_dir / "embedding.tsv" + +n_clusters = args.n_clusters +technology = args.technology +seed = args.seed + + +## Your code goes here +import json + +with open(args.config, "r") as f: + config = json.load(f) + +if config["refine"] and technology not in ["Visium", "ST"]: + raise Exception( + f"Invalid parameter combination. Refinement only works with Visium and ST not {technology}" + ) + +# TODO how to determine beta +beta = 49 + + +import random + +import numpy as np +import pandas as pd +import SpaGCN as spg +import torch + + +def get_anndata(args): + import anndata as ad + import scipy as sp + from PIL import Image + + X = sp.io.mmread(args.matrix) + if sp.sparse.issparse(X): + X = X.tocsr() + + observations = pd.read_table(args.observations, index_col=0) + features = pd.read_table(args.features, index_col=0) + + # Filter + if "selected" in observations.columns: + X = X[observations["selected"].to_numpy().nonzero()[0], :] + observations = observations.loc[lambda df: df["selected"]] + if "selected" in features.columns: + X = X[:, features["selected"].to_numpy().nonzero()[0]] + features = features.loc[lambda df: df["selected"]] + + coordinates = ( + pd.read_table(args.coordinates, index_col=0) + .loc[observations.index, :] + .to_numpy() + ) + + adata = ad.AnnData( + X=X, obs=observations, var=features, obsm={"spatial_pixel": coordinates} + ) + + if args.image is not None: + adata.uns["image"] = np.array(Image.open(args.image)) + else: + adata.uns["image"] = None + + return adata + + +adata = get_anndata(args) + + +# Set seed +random.seed(seed) +torch.manual_seed(seed) +np.random.seed(seed) + +if adata.uns["image"] is not None: + adj = spg.calculate_adj_matrix( + adata.obs["col"], + adata.obs["row"], + adata.obsm["spatial_pixel"][:, 0], + adata.obsm["spatial_pixel"][:, 1], + image=adata.uns["image"], + alpha=config["alpha"], + beta=beta, + histology=True, + ) +else: + adj = spg.calculate_adj_matrix(adata.obs["col"], adata.obs["row"], histology=False) + + +clf = spg.SpaGCN() + +# Find the l value given p +l = spg.search_l(config["p"], adj) +clf.set_l(l) + + +# Run +if config["method"] == "louvain": + # Search for suitable resolution + res = spg.search_res( + adata, adj, l, n_clusters, r_seed=seed, t_seed=seed, n_seed=seed + ) + clf.train( + adata, + adj, + init_spa=True, + init=config["method"], + res=res, + n_neighbors=config["n_neighbors"], + num_pcs=config["n_pcs"], + ) +else: + clf.train( + adata, + adj, + init_spa=True, + init=config["method"], + n_clusters=n_clusters, + num_pcs=config["n_pcs"], + ) +y_pred, prob = clf.predict() + +adata.obs["cluster"] = pd.Series(y_pred, index=adata.obs_names, dtype="category") + +if technology in ["Visium", "ST"] and config["refine"]: + # Do cluster refinement(optional) + adj_2d = spg.calculate_adj_matrix( + adata.obs["col"], adata.obs["row"], histology=False + ) + + shape = "hexagon" if technology == "Visium" else "square" + refined_pred = spg.refine( + sample_id=adata.obs_names.tolist(), + pred=adata.obs["cluster"].tolist(), + dis=adj_2d, + shape=shape, + ) + + adata.obs["refined_cluster"] = pd.Series( + refined_pred, index=adata.obs_names, dtype="category" + ) + + label_df = adata.obs[["refined_cluster"]] + +else: + label_df = adata.obs[["cluster"]] + + +## Write output +out_dir.mkdir(parents=True, exist_ok=True) + +label_df.columns = ["label"] +label_df.to_csv(label_file, sep="\t", index_label="") From 6676eee7a209a3ac3c9eaf804b6472c6499e57d8 Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Tue, 12 Dec 2023 11:53:21 +0100 Subject: [PATCH 07/14] Update Spatial_mgcn.yml --- method/Spatial_mgcn/Spatial_mgcn.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/method/Spatial_mgcn/Spatial_mgcn.yml b/method/Spatial_mgcn/Spatial_mgcn.yml index 8b137891..3e6fe9ea 100644 --- a/method/Spatial_mgcn/Spatial_mgcn.yml +++ b/method/Spatial_mgcn/Spatial_mgcn.yml @@ -1 +1,11 @@ - +channels: + - conda-forge +dependencies: + - python=3.8.18 + - anndata=0.9.2 + - numpy=1.24.4 + - pandas=2.0.3 + - pytorch=2.1.0 + - pip + - pip: + - SpaGCN==1.2.7 From d3264606fc536238c8cff14d1b0164c5fac8babd Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Tue, 12 Dec 2023 11:55:46 +0100 Subject: [PATCH 08/14] Rename Spatial_mgcn.py to Spatial-mgcn.py --- method/Spatial_mgcn/{Spatial_mgcn.py => Spatial-mgcn.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename method/Spatial_mgcn/{Spatial_mgcn.py => Spatial-mgcn.py} (100%) diff --git a/method/Spatial_mgcn/Spatial_mgcn.py b/method/Spatial_mgcn/Spatial-mgcn.py similarity index 100% rename from method/Spatial_mgcn/Spatial_mgcn.py rename to method/Spatial_mgcn/Spatial-mgcn.py From edb9c96f9b52adb19991dab0e17cef67cd1ac474 Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Tue, 12 Dec 2023 11:58:03 +0100 Subject: [PATCH 09/14] Rename Spatial-mgcn.py to Spatial-mgcn.py --- method/{Spatial_mgcn => Spatial-mgcn}/Spatial-mgcn.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename method/{Spatial_mgcn => Spatial-mgcn}/Spatial-mgcn.py (100%) diff --git a/method/Spatial_mgcn/Spatial-mgcn.py b/method/Spatial-mgcn/Spatial-mgcn.py similarity index 100% rename from method/Spatial_mgcn/Spatial-mgcn.py rename to method/Spatial-mgcn/Spatial-mgcn.py From 336109d1b5d711c0492507861482d3c4d4d04bcc Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Tue, 12 Dec 2023 11:58:43 +0100 Subject: [PATCH 10/14] Rename Spatial_mgcn.yml to Spatial-mgcn.yml --- .../Spatial_mgcn.yml => Spatial-mgcn/Spatial-mgcn.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename method/{Spatial_mgcn/Spatial_mgcn.yml => Spatial-mgcn/Spatial-mgcn.yml} (100%) diff --git a/method/Spatial_mgcn/Spatial_mgcn.yml b/method/Spatial-mgcn/Spatial-mgcn.yml similarity index 100% rename from method/Spatial_mgcn/Spatial_mgcn.yml rename to method/Spatial-mgcn/Spatial-mgcn.yml From bb677d0311f389ae5fe81896bede23d065c61297 Mon Sep 17 00:00:00 2001 From: Divya Sitani Date: Wed, 13 Dec 2023 09:30:53 +0100 Subject: [PATCH 11/14] Update Spatial-mgcn.yml --- method/Spatial-mgcn/Spatial-mgcn.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/method/Spatial-mgcn/Spatial-mgcn.yml b/method/Spatial-mgcn/Spatial-mgcn.yml index 3e6fe9ea..08b8c415 100644 --- a/method/Spatial-mgcn/Spatial-mgcn.yml +++ b/method/Spatial-mgcn/Spatial-mgcn.yml @@ -1,11 +1,16 @@ channels: - conda-forge + - defaults dependencies: - - python=3.8.18 - - anndata=0.9.2 - - numpy=1.24.4 - - pandas=2.0.3 - - pytorch=2.1.0 + - python=3.8.13 + - numpy=1.20.0 + - pandas=1.4.4 + - scipy=1.8.1 + - matplotlib=3.5.3 + - pytorch=1.11.0 - pip - pip: - - SpaGCN==1.2.7 + - stlearn==0.4.8 + - torch_geometric==2.1.0 + - torch_sparse==0.6.15 + - torch_scatter==2.0.9 From 160c2ffaa15918f0b587169ced559c0e646bc9a7 Mon Sep 17 00:00:00 2001 From: Kirti Biharie Date: Fri, 16 Feb 2024 09:41:21 +0000 Subject: [PATCH 12/14] Add implementation for Spatial-MGCN --- method/Spatial-mgcn/Spatial-mgcn.py | 234 +++++++++++++---------- method/Spatial-mgcn/Spatial-mgcn.yml | 7 +- method/Spatial-mgcn/config/config_1.json | 14 ++ 3 files changed, 155 insertions(+), 100 deletions(-) create mode 100644 method/Spatial-mgcn/config/config_1.json diff --git a/method/Spatial-mgcn/Spatial-mgcn.py b/method/Spatial-mgcn/Spatial-mgcn.py index 3be2a5c9..eacca3f1 100644 --- a/method/Spatial-mgcn/Spatial-mgcn.py +++ b/method/Spatial-mgcn/Spatial-mgcn.py @@ -1,12 +1,14 @@ #!/usr/bin/env python # Author_and_contribution: Niklas Mueller-Boetticher; created script +# Author_and_contribution: Kirti Biharie; Added Spatial-MGCN import argparse +CALC_ARI = False + parser = argparse.ArgumentParser( - description="""SpaGCN (https://www.nature.com/articles/s41592-021-01255-8) -Requirements: Visium or ST. Images can be used.""" + description="""Spatial-MGCN (https://doi.org/10.1093/bib/bbad262)""" ) parser.add_argument( @@ -51,6 +53,14 @@ required=False, ) +# Uncomment to calculate ARI every epoch as in original implementation +if CALC_ARI: + parser.add_argument( + "-g", "--groundtruth", + help="Groundtruth.", + required=False, + ) + args = parser.parse_args() from pathlib import Path @@ -65,34 +75,31 @@ technology = args.technology seed = args.seed - ## Your code goes here import json with open(args.config, "r") as f: config = json.load(f) -if config["refine"] and technology not in ["Visium", "ST"]: - raise Exception( - f"Invalid parameter combination. Refinement only works with Visium and ST not {technology}" - ) - -# TODO how to determine beta -beta = 49 - - import random - import numpy as np import pandas as pd -import SpaGCN as spg import torch - +import tempfile +import os +import sys +import scanpy as sc +import scipy as sp +import torch.optim +import sklearn.cluster +import sklearn.metrics +import tqdm def get_anndata(args): import anndata as ad - import scipy as sp + from PIL import Image + import scipy.io X = sp.io.mmread(args.matrix) if sp.sparse.issparse(X): @@ -115,8 +122,8 @@ def get_anndata(args): .to_numpy() ) - adata = ad.AnnData( - X=X, obs=observations, var=features, obsm={"spatial_pixel": coordinates} + adata = ad.AnnData( # Rename spatial_pixel to spatial for Spatial-mgcn + X=X, obs=observations, var=features, obsm={"spatial": coordinates} ) if args.image is not None: @@ -129,88 +136,119 @@ def get_anndata(args): adata = get_anndata(args) +if CALC_ARI: + labels = pd.read_table(args.groundtruth, index_col=0) + adata = adata[adata.obs_names.isin(labels.index)] + labels = labels.loc[adata.obs_names] # Set seed random.seed(seed) torch.manual_seed(seed) np.random.seed(seed) - -if adata.uns["image"] is not None: - adj = spg.calculate_adj_matrix( - adata.obs["col"], - adata.obs["row"], - adata.obsm["spatial_pixel"][:, 0], - adata.obsm["spatial_pixel"][:, 1], - image=adata.uns["image"], - alpha=config["alpha"], - beta=beta, - histology=True, - ) -else: - adj = spg.calculate_adj_matrix(adata.obs["col"], adata.obs["row"], histology=False) - - -clf = spg.SpaGCN() - -# Find the l value given p -l = spg.search_l(config["p"], adj) -clf.set_l(l) - - -# Run -if config["method"] == "louvain": - # Search for suitable resolution - res = spg.search_res( - adata, adj, l, n_clusters, r_seed=seed, t_seed=seed, n_seed=seed - ) - clf.train( - adata, - adj, - init_spa=True, - init=config["method"], - res=res, - n_neighbors=config["n_neighbors"], - num_pcs=config["n_pcs"], - ) -else: - clf.train( - adata, - adj, - init_spa=True, - init=config["method"], - n_clusters=n_clusters, - num_pcs=config["n_pcs"], - ) -y_pred, prob = clf.predict() - -adata.obs["cluster"] = pd.Series(y_pred, index=adata.obs_names, dtype="category") - -if technology in ["Visium", "ST"] and config["refine"]: - # Do cluster refinement(optional) - adj_2d = spg.calculate_adj_matrix( - adata.obs["col"], adata.obs["row"], histology=False - ) - - shape = "hexagon" if technology == "Visium" else "square" - refined_pred = spg.refine( - sample_id=adata.obs_names.tolist(), - pred=adata.obs["cluster"].tolist(), - dis=adj_2d, - shape=shape, - ) - - adata.obs["refined_cluster"] = pd.Series( - refined_pred, index=adata.obs_names, dtype="category" - ) - - label_df = adata.obs[["refined_cluster"]] - -else: - label_df = adata.obs[["cluster"]] - - -## Write output -out_dir.mkdir(parents=True, exist_ok=True) - -label_df.columns = ["label"] -label_df.to_csv(label_file, sep="\t", index_label="") +torch.cuda.manual_seed(seed) + +# Work in a temprary folder +with tempfile.TemporaryDirectory() as tmpdir: + gitdir = f"{str(tmpdir)}/Spatial-MGCN" + + # Clone the repository to the specific commit + os.system( + f""" + git clone https://github.com/cs-wangbo/Spatial-MGCN.git {gitdir} + cd {gitdir} + git reset --hard cf4412d + """) + + # Set working directory as Spatial-MGCN directory + sys.path.append(f"{gitdir}/Spatial-MGCN") + import utils + import models + + # Normalize data: min_cells, calculate HVG and scale + sc.pp.filter_genes(adata, min_cells=100) + sc.pp.highly_variable_genes(adata, flavor="seurat_v3", n_top_genes=config["fdim"]) + adata = adata[:, adata.var['highly_variable']].copy() + adata.X = adata.X / np.sum(adata.X, axis=1).reshape(-1, 1) * 10000 + adata.X = sp.sparse.csr_matrix(adata.X) + sc.pp.scale(adata, zero_center=False, max_value=10) + + # Calculate graphs + fadj = utils.features_construct_graph(adata.X, k=config["k"]) + sadj, graph_nei, graph_neg = utils.spatial_construct_graph1(adata, radius=config["radius"]) + + adata.obsm["fadj"] = fadj + adata.obsm["sadj"] = sadj + adata.obsm["graph_nei"] = graph_nei.numpy() + adata.obsm["graph_neg"] = graph_neg.numpy() + + features = torch.FloatTensor(adata.X.todense()) + + nfadj = utils.normalize_sparse_matrix(fadj + sp.eye(fadj.shape[0])) + nfadj = sp.sparse.csr_matrix(nfadj) + nfadj = utils.sparse_mx_to_torch_sparse_tensor(nfadj) + + nsadj = utils.normalize_sparse_matrix(sadj + sp.eye(sadj.shape[0])) + nsadj = sp.sparse.csr_matrix(nsadj) + nsadj = utils.sparse_mx_to_torch_sparse_tensor(nsadj) + + graph_nei = torch.LongTensor(adata.obsm['graph_nei']) + graph_neg = torch.LongTensor(adata.obsm['graph_neg']) + + # Create model + cuda = torch.cuda.is_available() + + if cuda: + features = features.cuda() + nsadj = nsadj.cuda() + nfadj = nfadj.cuda() + graph_nei = graph_nei.cuda() + graph_neg = graph_neg.cuda() + + model = models.Spatial_MGCN(nfeat=config["fdim"], + nhid1=config["nhid1"], + nhid2=config["nhid2"], + dropout=config["dropout"]) + + if cuda: + model.cuda() + + optimizer = torch.optim.Adam(model.parameters(), lr=config["lr"], weight_decay=config["weight_decay"]) + + # Train model + epoch_max = 0 + ari_max = 0 + idx_max = [] + mean_max = [] + emb_max = [] + + for epoch in tqdm.tqdm(range(config["epochs"])): + model.train() + optimizer.zero_grad() + com1, com2, emb, pi, disp, mean = model(features, nsadj, nfadj) + zinb_loss = utils.ZINB(pi, theta=disp, ridge_lambda=0).loss(features, mean, mean=True) + reg_loss = utils.regularization_loss(emb, graph_nei, graph_neg) + con_loss = utils.consistency_loss(com1, com2) + total_loss = config["alpha"] * zinb_loss + config["beta"] * con_loss + config["gamma"] * reg_loss + emb = pd.DataFrame(emb.cpu().detach().numpy()).fillna(0).values + total_loss.backward() + optimizer.step() + + kmeans = sklearn.cluster.KMeans(n_clusters=args.n_clusters, n_init=10).fit(emb) + idx = kmeans.labels_ + + if CALC_ARI: + ari_res = sklearn.metrics.adjusted_rand_score(labels.to_numpy()[:,0], idx) + if ari_res > ari_max: + ari_max = ari_res + idx_max = idx + emb_max = emb + else: + idx_max = idx + emb_max = emb + + # Write output + emb_df = pd.DataFrame(emb_max, index=adata.obs_names) + label_df = pd.DataFrame(idx_max, index=adata.obs_names, columns=["label"]) + + emb_df.to_csv(embedding_file, sep="\t", index_label="") + label_df.to_csv(label_file, sep="\t", index_label="") diff --git a/method/Spatial-mgcn/Spatial-mgcn.yml b/method/Spatial-mgcn/Spatial-mgcn.yml index 08b8c415..a2e36f06 100644 --- a/method/Spatial-mgcn/Spatial-mgcn.yml +++ b/method/Spatial-mgcn/Spatial-mgcn.yml @@ -3,14 +3,17 @@ channels: - defaults dependencies: - python=3.8.13 - - numpy=1.20.0 + - numpy=1.22.0 - pandas=1.4.4 - scipy=1.8.1 - matplotlib=3.5.3 - pytorch=1.11.0 - pip - pip: - - stlearn==0.4.8 + - stlearn==0.4.12 - torch_geometric==2.1.0 - torch_sparse==0.6.15 - torch_scatter==2.0.9 + - git+https://github.com/cs-wangbo/Spatial-MGCN@cf4412df6db6276e0c8a3f036ff0b1661adfdb35 + - python-louvain==0.16 + - scikit-misc==0.2.0 diff --git a/method/Spatial-mgcn/config/config_1.json b/method/Spatial-mgcn/config/config_1.json new file mode 100644 index 00000000..99366eb1 --- /dev/null +++ b/method/Spatial-mgcn/config/config_1.json @@ -0,0 +1,14 @@ +{ + "epochs": 200, + "lr": 0.001, + "weight_decay": 5e-4, + "k": 14, + "radius": 560, + "nhid1": 128, + "nhid2": 64, + "dropout": 0, + "alpha": 1, + "beta": 10, + "gamma": 0.1, + "fdim": 3000 +} \ No newline at end of file From 7205064fb6d4b278f5c4dcebf4370c553e625e90 Mon Sep 17 00:00:00 2001 From: Kirti Biharie Date: Fri, 16 Feb 2024 09:59:43 +0000 Subject: [PATCH 13/14] Add optargs.json --- method/Spatial-mgcn/Spatial-mgcn_optargs.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 method/Spatial-mgcn/Spatial-mgcn_optargs.json diff --git a/method/Spatial-mgcn/Spatial-mgcn_optargs.json b/method/Spatial-mgcn/Spatial-mgcn_optargs.json new file mode 100644 index 00000000..3a9880a2 --- /dev/null +++ b/method/Spatial-mgcn/Spatial-mgcn_optargs.json @@ -0,0 +1,7 @@ +{ + "matrix": "counts", + "integrated_feature_selection": true, + "image": false, + "neighbors": false, + "config_file": true +} \ No newline at end of file From f3a8e97f328e8f17b1da77f2c2729c71dd115f6f Mon Sep 17 00:00:00 2001 From: Kirti Biharie Date: Sun, 10 Mar 2024 15:06:10 +0000 Subject: [PATCH 14/14] Update yml and use standard preprocessing --- method/Spatial-mgcn/Spatial-mgcn.py | 14 ++++++++------ method/Spatial-mgcn/Spatial-mgcn.yml | 1 - method/Spatial-mgcn/Spatial-mgcn_optargs.json | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/method/Spatial-mgcn/Spatial-mgcn.py b/method/Spatial-mgcn/Spatial-mgcn.py index eacca3f1..78cb174e 100644 --- a/method/Spatial-mgcn/Spatial-mgcn.py +++ b/method/Spatial-mgcn/Spatial-mgcn.py @@ -165,12 +165,14 @@ def get_anndata(args): import models # Normalize data: min_cells, calculate HVG and scale - sc.pp.filter_genes(adata, min_cells=100) - sc.pp.highly_variable_genes(adata, flavor="seurat_v3", n_top_genes=config["fdim"]) - adata = adata[:, adata.var['highly_variable']].copy() - adata.X = adata.X / np.sum(adata.X, axis=1).reshape(-1, 1) * 10000 - adata.X = sp.sparse.csr_matrix(adata.X) - sc.pp.scale(adata, zero_center=False, max_value=10) + # sc.pp.filter_genes(adata, min_cells=100) + # sc.pp.highly_variable_genes(adata, flavor="seurat_v3", n_top_genes=config["fdim"]) + # adata = adata[:, adata.var['highly_variable']].copy() + # adata.X = adata.X / np.sum(adata.X, axis=1).reshape(-1, 1) * 10000 + # adata.X = sp.sparse.csr_matrix(adata.X) + # sc.pp.scale(adata, zero_center=False, max_value=10) + + config["fdim"] = len(adata.var_names) # Calculate graphs fadj = utils.features_construct_graph(adata.X, k=config["k"]) diff --git a/method/Spatial-mgcn/Spatial-mgcn.yml b/method/Spatial-mgcn/Spatial-mgcn.yml index a2e36f06..ba707e1c 100644 --- a/method/Spatial-mgcn/Spatial-mgcn.yml +++ b/method/Spatial-mgcn/Spatial-mgcn.yml @@ -14,6 +14,5 @@ dependencies: - torch_geometric==2.1.0 - torch_sparse==0.6.15 - torch_scatter==2.0.9 - - git+https://github.com/cs-wangbo/Spatial-MGCN@cf4412df6db6276e0c8a3f036ff0b1661adfdb35 - python-louvain==0.16 - scikit-misc==0.2.0 diff --git a/method/Spatial-mgcn/Spatial-mgcn_optargs.json b/method/Spatial-mgcn/Spatial-mgcn_optargs.json index 3a9880a2..a1f69b92 100644 --- a/method/Spatial-mgcn/Spatial-mgcn_optargs.json +++ b/method/Spatial-mgcn/Spatial-mgcn_optargs.json @@ -1,6 +1,6 @@ { "matrix": "counts", - "integrated_feature_selection": true, + "integrated_feature_selection": false, "image": false, "neighbors": false, "config_file": true