Skip to content

Commit d0db8bf

Browse files
committed
networks per sample done with loading of the edges
1 parent 4b4e926 commit d0db8bf

3 files changed

Lines changed: 168 additions & 52 deletions

File tree

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,75 @@
1+
import pandas as pd
12
from mosna import mosna
3+
from package.utils.emit_qt_progress import emit_qt_progress, emit_qt_info
4+
from package.core.NAS.merge_niche_pheno import merge_niche_pheno
5+
from package.core.NAS.mosna_figures import mosna_figures
26

3-
def niches_per_sample():
4-
return 0
7+
def niches_per_sample(method, net_dir, save_dir, data_info ,pheno_col, uniq_phenotype, stat_funcs, stat_names, id_level_1, id_level_2,
8+
reducer_type, clusterer_type, n_neighbors, metric, n_clusters, resolution, min_dist, dim_clust,
9+
min_cluster_size, k_cluster, normalize):
10+
11+
emit_qt_info("[PROCESS] Spatial Omic Features for all networks")
12+
emit_qt_progress(0,3, "[PROCESS] Niches Analysis")
13+
14+
var_aggreg = mosna.compute_spatial_omic_features_single_network(
15+
method=method,
16+
net_dir=net_dir,
17+
attributes_col=pheno_col,
18+
data_info=data_info,
19+
use_attributes=uniq_phenotype,
20+
make_onehot=True,
21+
stat_funcs=stat_funcs,
22+
stat_names=stat_names,
23+
id_level_1=id_level_1,
24+
id_level_2=id_level_2,
25+
parallel_groups='max',
26+
memory_limit='max',
27+
save_intermediate_results=False,
28+
dir_save_interm=None,
29+
verbose=0,
30+
)
31+
32+
emit_qt_progress(1,3, "[PROCESS] Niches Analysis")
33+
34+
emit_qt_info("[PROCESS] Reduction and Clustering of Spatial Niches")
35+
cluster_labels, _, _, _ = mosna.get_clusterer(
36+
data=var_aggreg.values,
37+
data_dir=save_dir,
38+
reducer_type=reducer_type,
39+
clusterer_type=clusterer_type,
40+
n_neighbors=n_neighbors,
41+
metric=metric,
42+
n_clusters=n_clusters,
43+
resolution=resolution,
44+
min_dist=min_dist,
45+
dim_clust=dim_clust,
46+
min_cluster_size=min_cluster_size,
47+
use_gpu=False,
48+
k_cluster=k_cluster,
49+
verbose=0,
50+
)
51+
emit_qt_progress(2,3, "[PROCESS] Niches Analysis")
52+
53+
cell_types = merge_niche_pheno(net_dir, pheno_col, cluster_labels)
54+
55+
emit_qt_info("[PROCESS] Generate Niches Composition")
56+
if normalize == 'all':
57+
for normalization in ['total', 'niche', 'obs', 'clr', 'niche&obs']:
58+
counts = mosna.make_niches_composition(
59+
var=cell_types,
60+
niches=cluster_labels,
61+
var_label=pheno_col,
62+
normalize=normalization
63+
)
64+
save_dir_norm = save_dir / f'{normalization}'
65+
save_dir_norm.mkdir(exist_ok=True, parents=True)
66+
mosna_figures(cluster_labels, counts, save_dir_norm)
67+
else:
68+
counts = mosna.make_niches_composition(
69+
var=cell_types,
70+
niches=cluster_labels,
71+
var_label=pheno_col,
72+
normalize=normalize
73+
)
74+
mosna_figures(cluster_labels, counts, save_dir)
75+
emit_qt_progress(3,3, "[PROCESS] Niches Analysis")

package/core/tysserand/draw_per_sample.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from ...utils.read_extension import get_opener
2121
from ...utils.find_sample_from_file import find_sample_from_file
2222

23-
def draw_per_sample(file,
23+
def draw_per_sample(node_file,
2424
X_position,
2525
Y_position,
2626
pheno_col,
@@ -31,20 +31,24 @@ def draw_per_sample(file,
3131
temp_folder,
3232
patient_colmun,
3333
sample_column,
34-
extension):
34+
extension,
35+
edges_file = None):
3536

3637
opener = get_opener(extension)
37-
node = opener(file)
38+
node = opener(node_file)
3839

39-
patient, sample = find_sample_from_file(file, patient_colmun, sample_column)
40+
patient, sample = find_sample_from_file(node_file, patient_colmun, sample_column)
4041
patient = int("".join(c for c in patient if c.isdigit()))
4142

4243
clustering = node[pheno_col]
4344

4445
coords = node[[X_position,Y_position]].to_numpy()
45-
pairs = ty.build_delaunay(coords)
46-
47-
pairs = ty.link_solitaries(coords, pairs, method=method, min_neighbors=min_neighbors, verbose=0)
46+
47+
if edges_file is None:
48+
pairs = ty.build_delaunay(coords)
49+
pairs = ty.link_solitaries(coords, pairs, method=method, min_neighbors=min_neighbors, verbose=0)
50+
else:
51+
pairs = pd.read_parquet(edges_file)
4852

4953
fig, ax = ty.plot_network(
5054
coords, pairs,labels=clustering,

package/niche_analysis.py

Lines changed: 84 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from package.core.tysserand.draw_per_sample import draw_per_sample
1515
from package.utils.find_sample import find_sample
1616
from package.core.tysserand.generate_cmap import generate_cmap
17+
from package.utils.find_sample_from_file import find_sample_from_file
1718

1819
from mosna import mosna
1920

@@ -129,15 +130,16 @@ def main():
129130
save_dir.mkdir(exist_ok=True, parents=True)
130131

131132
args_list = [(
132-
patient_sample,
133+
node_file,
133134
X,
134135
Y,
135136
'niches',
136137
c_map,
137138
'delaunay',3,
138139
save_dir,'None',
139140
kwargs['id_level_1'],kwargs['id_level_2'],
140-
'parquet')for patient_sample in files]
141+
'parquet', '/'.join(node_file.rsplit('/', 1)[:-1] + [node_file.rsplit('/', 1)[-1].replace('nodes_', 'edges_', 1)])
142+
) for node_file in files]
141143

142144
process_map(
143145
worker_draw_wrapper,
@@ -148,50 +150,89 @@ def main():
148150
)
149151

150152
elif per_sample:
151-
153+
from package.core.NAS.niches_per_sample import niches_per_sample
152154
save_dir = save_dir = working_dir / "Niche_Analysis/Per_sample" / config['Saving directory']
153155
save_dir.mkdir(exist_ok=True, parents=True)
154-
kwargs = {
155-
"method": config.get("method", "NAS"),
156-
"net_dir": net_dir,
157-
"save_dir": save_dir,
158-
"temp_dir": net_dir,
159-
"pheno_col": config["Phenotype column"],
160-
"uniq_phenotype": uniq_phenotype,
161-
"stat_funcs": config.get("stat_funcs", "default"),
162-
"stat_names": config.get("stat_names", "default"),
163-
"id_level_1": config.get("Patient column name", "patient"),
164-
"id_level_2": config.get("Sample column name", "sample"),
165156

166-
############# Clustering / réduction
167-
"reducer_type": config["Per sample"].get("reducer_type", "umap"),
168-
"clusterer_type": config["Per sample"].get("clusterer_type", "leiden"),
169-
"n_neighbors": int(config["Per sample"].get("n_neighbors", 15)),
170-
"metric": config["Per sample"].get("metric", "euclidean"),
171-
"n_clusters": int(config["Per sample"].get("n_clusters", 15)),
172-
"resolution": float(config["Per sample"].get("resolution", 0.005)),
173-
"min_dist": float(config["Per sample"].get("min_dist", 0.0)),
174-
"dim_clust": int(config["Per sample"].get("dim_clust", 2)),
175-
"min_cluster_size": float(config["Per sample"].get("min_cluster_size", 0.001)),
176-
"k_cluster": int(config["Per sample"].get("k_cluster", 8)),
177-
178-
########## Normalisation composition niches
179-
"normalize": config["Per sample"].get("normalize", "total"),
180-
}
181-
from package.core.NAS.niches_per_sample import niches_per_sample
182-
niches_per_sample(**kwargs)
183-
184-
emit_qt_info('[INFO] Niches found for each samples')
185-
186-
for path in save_dir.glob("reducer-umap*"):
187-
if path.is_dir():
188-
shutil.rmtree(path)
189-
save_config(save_dir, config)
190-
191-
X, Y = config['X coordinates column for niches'], config['Y coordinates column for niches']
192-
193-
if X is not None and Y is not None:
194-
pass
157+
files = find_sample(net_dir, 'parquet', config.get("Patient column name", "patient"), config.get("Sample column name", "sample"))
158+
data_info = []
159+
for file in files:
160+
if config.get("Sample column name", "sample") is None:
161+
patient = find_sample_from_file(file, config.get("Patient column name", "patient"), config.get("Sample column name", "sample"))
162+
data_info.append([patient])
163+
else:
164+
patient, sample = find_sample_from_file(file, config.get("Patient column name", "patient"), config.get("Sample column name", "sample"))
165+
data_info.append([patient, sample])
166+
167+
for sample in data_info:
168+
if config.get("Sample column name", "sample") is None:
169+
patient_sample = f'{config.get("Patient column name", "patient")}-{sample[0]}'
170+
else:
171+
patient_sample = f'{config.get("Patient column name", "patient")}-{sample[0]}_{config.get("Sample column name", "sample")}-{sample[1]}'
172+
save_dir_sample = save_dir / f'{patient_sample}'
173+
174+
kwargs = {
175+
"method": config.get("method", "NAS"),
176+
"net_dir": net_dir,
177+
"save_dir": save_dir_sample,
178+
"data_info": sample,
179+
"pheno_col": config["Phenotype column"],
180+
"uniq_phenotype": uniq_phenotype,
181+
"stat_funcs": config.get("stat_funcs", "default"),
182+
"stat_names": config.get("stat_names", "default"),
183+
"id_level_1": config.get("Patient column name", "patient"),
184+
"id_level_2": config.get("Sample column name", "sample"),
185+
186+
############# Clustering / réduction
187+
"reducer_type": config["Per sample"].get("reducer_type", "umap"),
188+
"clusterer_type": config["Per sample"].get("clusterer_type", "leiden"),
189+
"n_neighbors": int(config["Per sample"].get("n_neighbors", 15)),
190+
"metric": config["Per sample"].get("metric", "euclidean"),
191+
"n_clusters": int(config["Per sample"].get("n_clusters", 15)),
192+
"resolution": float(config["Per sample"].get("resolution", 0.005)),
193+
"min_dist": float(config["Per sample"].get("min_dist", 0.0)),
194+
"dim_clust": int(config["Per sample"].get("dim_clust", 2)),
195+
"min_cluster_size": float(config["Per sample"].get("min_cluster_size", 0.001)),
196+
"k_cluster": int(config["Per sample"].get("k_cluster", 8)),
197+
198+
########## Normalisation composition niches
199+
"normalize": config["Per sample"].get("normalize", "total"),
200+
}
201+
202+
niches_per_sample(**kwargs)
203+
204+
emit_qt_info('[INFO] Niches found for each samples')
205+
206+
for path in save_dir_sample.glob("reducer-umap*"):
207+
if path.is_dir():
208+
shutil.rmtree(path)
209+
save_config(save_dir_sample, config)
210+
211+
X, Y = config['X coordinates column for niches'], config['Y coordinates column for niches']
212+
213+
if X is not None and Y is not None:
214+
c_map = generate_cmap(net_dir, 'niche', 'parquet', kwargs['id_level_1'], kwargs['id_level_2'])
215+
files = find_sample(net_dir, 'parquet', kwargs['id_level_1'], kwargs['id_level_2'])
216+
cpu_max = verif_cpu(config['CPU'], len(files))
217+
218+
save_dir_sample_tysserand = save_dir_sample / 'Tysserand_Network_Niches'
219+
save_dir_sample_tysserand.mkdir(exist_ok=True, parents=True)
220+
221+
node_file = net_dir / f'nodes_{patient_sample}.parquet'
222+
edge_file = net_dir / f'edges_{patient_sample}.parquet'
223+
224+
args_list = [
225+
node_file,
226+
X,
227+
Y,
228+
'niches',
229+
c_map,
230+
'delaunay',3,
231+
save_dir_sample_tysserand,'None',
232+
kwargs['id_level_1'],kwargs['id_level_2'],
233+
'parquet',
234+
edge_file]
235+
draw_per_sample(args_list)
195236

196237
if __name__ == '__main__':
197238
main()

0 commit comments

Comments
 (0)