scMultiChat 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- MultiChat/Analysis/Intra_strength.py +1758 -0
- MultiChat/Analysis/Processing.py +152 -0
- MultiChat/Analysis/__init__.py +2 -0
- MultiChat/Heterogeneous_g_emb/__init__.py +13 -0
- MultiChat/Heterogeneous_g_emb/_settings.py +156 -0
- MultiChat/Heterogeneous_g_emb/_utils.py +143 -0
- MultiChat/Heterogeneous_g_emb/_version.py +3 -0
- MultiChat/Heterogeneous_g_emb/plotting/__init__.py +19 -0
- MultiChat/Heterogeneous_g_emb/plotting/_palettes.py +180 -0
- MultiChat/Heterogeneous_g_emb/plotting/_plot.py +1498 -0
- MultiChat/Heterogeneous_g_emb/plotting/_post_training.py +742 -0
- MultiChat/Heterogeneous_g_emb/plotting/_utils.py +103 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/__init__.py +26 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/_general.py +91 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/_pca.py +182 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/_qc.py +727 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/_utils.py +60 -0
- MultiChat/Heterogeneous_g_emb/preprocessing/_variable_genes.py +82 -0
- MultiChat/Heterogeneous_g_emb/readwrite.py +250 -0
- MultiChat/Heterogeneous_g_emb/tools/__init__.py +23 -0
- MultiChat/Heterogeneous_g_emb/tools/_gene_scores.py +346 -0
- MultiChat/Heterogeneous_g_emb/tools/_general.py +71 -0
- MultiChat/Heterogeneous_g_emb/tools/_integration.py +197 -0
- MultiChat/Heterogeneous_g_emb/tools/_pbg.py +1184 -0
- MultiChat/Heterogeneous_g_emb/tools/_post_training.py +919 -0
- MultiChat/Heterogeneous_g_emb/tools/_umap.py +58 -0
- MultiChat/Heterogeneous_g_emb/tools/_utils.py +253 -0
- MultiChat/Model/Layers.py +116 -0
- MultiChat/Model/__init__.py +3 -0
- MultiChat/Model/model_training.py +166 -0
- MultiChat/Model/modules.py +93 -0
- MultiChat/Model/utilities.py +234 -0
- MultiChat/Plot/Visualization.py +470 -0
- MultiChat/Plot/__init__.py +1 -0
- MultiChat/__init__.py +12 -0
- scmultichat-0.1.0.dist-info/METADATA +156 -0
- scmultichat-0.1.0.dist-info/RECORD +39 -0
- scmultichat-0.1.0.dist-info/WHEEL +5 -0
- scmultichat-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1184 @@
|
|
|
1
|
+
"""PyTorch-BigGraph (PBG) for learning graph embeddings"""
|
|
2
|
+
|
|
3
|
+
from random import shuffle
|
|
4
|
+
from typing import Dict
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import anndata as ad
|
|
8
|
+
import os
|
|
9
|
+
import json
|
|
10
|
+
from tqdm.auto import tqdm
|
|
11
|
+
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
import attr
|
|
14
|
+
from torchbiggraph.config import (
|
|
15
|
+
add_to_sys_path,
|
|
16
|
+
ConfigFileLoader
|
|
17
|
+
)
|
|
18
|
+
from torchbiggraph.converters.importers import (
|
|
19
|
+
convert_input_data,
|
|
20
|
+
TSVEdgelistReader
|
|
21
|
+
)
|
|
22
|
+
from torchbiggraph.train import train
|
|
23
|
+
from torchbiggraph.util import (
|
|
24
|
+
set_logging_verbosity,
|
|
25
|
+
setup_logging,
|
|
26
|
+
SubprocessInitializer,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
from ._utils import _randomize_matrix
|
|
30
|
+
from .._settings import settings
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def gen_graph(list_CP=None,
|
|
34
|
+
list_PM=None,
|
|
35
|
+
list_PK=None,
|
|
36
|
+
list_CG=None,
|
|
37
|
+
list_CC=None,
|
|
38
|
+
list_adata=None,
|
|
39
|
+
prefix_C='C',
|
|
40
|
+
prefix_P='P',
|
|
41
|
+
prefix_M='M',
|
|
42
|
+
prefix_K='K',
|
|
43
|
+
prefix_G='G',
|
|
44
|
+
prefix='E',
|
|
45
|
+
layer='hge',
|
|
46
|
+
copy=False,
|
|
47
|
+
dirname='graph0',
|
|
48
|
+
add_edge_weights=None,
|
|
49
|
+
use_highly_variable=True,
|
|
50
|
+
use_top_pcs=True,
|
|
51
|
+
use_top_pcs_CP=None,
|
|
52
|
+
use_top_pcs_PM=None,
|
|
53
|
+
use_top_pcs_PK=None,
|
|
54
|
+
get_marker_significance=False,
|
|
55
|
+
fold_null_nodes = 1.0,
|
|
56
|
+
):
|
|
57
|
+
"""Generate graph for PBG training.
|
|
58
|
+
|
|
59
|
+
Observations and variables of each Anndata object will be encoded
|
|
60
|
+
as nodes (entities). The non-zero values in `.layers['hge']` (by default)
|
|
61
|
+
or `.X` (if `.layers['hge']` does not exist) indicate the edges
|
|
62
|
+
between nodes. The values of `.layers['hge']` or `.X` will be used
|
|
63
|
+
as the edge weights if `add_edge_weights` True.
|
|
64
|
+
|
|
65
|
+
Nodes between different anndata objects will be automatically matched
|
|
66
|
+
based on `.obs_names` and `.var_names`. Each anndata object indicates one
|
|
67
|
+
or more relation types.
|
|
68
|
+
|
|
69
|
+
It also generates an accompanying file 'entity_alias.tsv' to map
|
|
70
|
+
the indices to the aliases used in the graph.
|
|
71
|
+
|
|
72
|
+
Note when `add_edge_weights` is True, `list_CG` will only generate
|
|
73
|
+
one relation of cells and genes, as opposed to multiple relations
|
|
74
|
+
based on discretized levels.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
list_CP: `list`, optional (default: None)
|
|
79
|
+
A list of anndata objects that store ATAC-seq data (Cells by Peaks)
|
|
80
|
+
The default weight of cell-peak relation type is 1.0.
|
|
81
|
+
list_PM: `list`, optional (default: None)
|
|
82
|
+
A list of anndata objects that store relation between Peaks and Motifs
|
|
83
|
+
list_PK: `list`, optional (default: None)
|
|
84
|
+
A list of anndata objects that store relation between Peaks and Kmers
|
|
85
|
+
list_CG: `list`, optional (default: None)
|
|
86
|
+
A list of anndata objects that store RNA-seq data (Cells by Genes)
|
|
87
|
+
list_CC: `list`, optional (default: None)
|
|
88
|
+
A list of anndata objects that store relation between Cells
|
|
89
|
+
from two conditions
|
|
90
|
+
list_adata: `list`, optional (default: None)
|
|
91
|
+
A list of anndata objects. `.obs_names` and `.var_names`
|
|
92
|
+
between anndata objects will be automatically matched.
|
|
93
|
+
If `list_adata` is specified, the other lists including
|
|
94
|
+
`list_CP`, `list_PM`,`list_PK`, `list_CG`, `list_CC` will be ignored.
|
|
95
|
+
prefix_C: `str`, optional (default: 'C')
|
|
96
|
+
Prefix to indicate the entity type of cells
|
|
97
|
+
prefix_G: `str`, optional (default: 'G')
|
|
98
|
+
Prefix to indicate the entity type of genes
|
|
99
|
+
prefix: `str`, optional (default: 'E')
|
|
100
|
+
Prefix to indicate general entities in `list_adata`
|
|
101
|
+
layer: `str`, optional (default: 'hge')
|
|
102
|
+
The layer in AnnData to use for constructing the graph.
|
|
103
|
+
If `layer` is None or the specificed layer does not exist,
|
|
104
|
+
`.X` in AnnData will be used instead.
|
|
105
|
+
dirname: `str`, (default: 'graph0')
|
|
106
|
+
The name of the directory in which each graph will be stored
|
|
107
|
+
add_edge_weights: `bool`, optional (default: None)
|
|
108
|
+
If True, the column of edge weigths will be added.
|
|
109
|
+
If `list_adata` is specified, `add_edge_weights` is set True
|
|
110
|
+
by default. Otherwise, it is set False.
|
|
111
|
+
use_highly_variable: `bool`, optional (default: True)
|
|
112
|
+
Use highly variable genes. Only valid for list_CG.
|
|
113
|
+
use_top_pcs: `bool`, optional (default: True)
|
|
114
|
+
Use top-PCs-associated features for CP, PM, PK
|
|
115
|
+
use_top_pcs_CP: `bool`, optional (default: None)
|
|
116
|
+
Use top-PCs-associated features for CP
|
|
117
|
+
Once specified, it will overwrite `use_top_pcs`
|
|
118
|
+
use_top_pcs_PM: `bool`, optional (default: None)
|
|
119
|
+
Use top-PCs-associated features for PM
|
|
120
|
+
Once specified, it will overwrite `use_top_pcs`
|
|
121
|
+
use_top_pcs_PK: `bool`, optional (default: None)
|
|
122
|
+
Use top-PCs-associated features for PK
|
|
123
|
+
Once specified, it will overwrite `use_top_pcs`
|
|
124
|
+
copy: `bool`, optional (default: False)
|
|
125
|
+
If True, it returns the graph file as a data frame
|
|
126
|
+
Returns
|
|
127
|
+
-------
|
|
128
|
+
If `copy` is True,
|
|
129
|
+
edges: `pd.DataFrame`
|
|
130
|
+
The edges of the graph used for PBG training.
|
|
131
|
+
Each line contains information about one edge.
|
|
132
|
+
Using tabs as separators, each line contains the identifiers of
|
|
133
|
+
the source entities, the relation types and the target entities.
|
|
134
|
+
|
|
135
|
+
updates `.settings.pbg_params` with the following parameters.
|
|
136
|
+
entity_path: `str`
|
|
137
|
+
The path of the directory containing entity count files.
|
|
138
|
+
edge_paths: `list`
|
|
139
|
+
A list of paths to directories containing (partitioned) edgelists.
|
|
140
|
+
Typically a single path is provided.
|
|
141
|
+
entities: `dict`
|
|
142
|
+
The entity types.
|
|
143
|
+
relations: `list`
|
|
144
|
+
The relation types.
|
|
145
|
+
|
|
146
|
+
updates `.settings.graph_stats` with the following parameters.
|
|
147
|
+
`dirname`: `dict`
|
|
148
|
+
Statistics of input graph
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
if sum(list(map(lambda x: x is None,
|
|
152
|
+
[list_CP,
|
|
153
|
+
list_PM,
|
|
154
|
+
list_PK,
|
|
155
|
+
list_CG,
|
|
156
|
+
list_CC,
|
|
157
|
+
list_adata]))) == 6:
|
|
158
|
+
return 'No graph is generated'
|
|
159
|
+
if get_marker_significance:
|
|
160
|
+
gen_graph(list_CP=list_CP,
|
|
161
|
+
list_PM=list_PM,
|
|
162
|
+
list_PK=list_PK,
|
|
163
|
+
list_CG=list_CG,
|
|
164
|
+
list_CC=list_CC,
|
|
165
|
+
prefix_C=prefix_C,
|
|
166
|
+
prefix_P=prefix_P,
|
|
167
|
+
prefix_M=prefix_M,
|
|
168
|
+
prefix_K=prefix_K,
|
|
169
|
+
prefix_G=prefix_G,
|
|
170
|
+
layer=layer,
|
|
171
|
+
copy=copy,
|
|
172
|
+
dirname=dirname,
|
|
173
|
+
add_edge_weights=add_edge_weights,
|
|
174
|
+
use_highly_variable=use_highly_variable,
|
|
175
|
+
use_top_pcs=use_top_pcs,
|
|
176
|
+
use_top_pcs_CP=use_top_pcs_CP,
|
|
177
|
+
use_top_pcs_PM=use_top_pcs_PM,
|
|
178
|
+
use_top_pcs_PK=use_top_pcs_PK,
|
|
179
|
+
get_marker_significance=False,
|
|
180
|
+
)
|
|
181
|
+
dirname_orig = dirname
|
|
182
|
+
dirname += "_with_sig"
|
|
183
|
+
filepath = os.path.join(settings.workdir, 'pbg', dirname)
|
|
184
|
+
settings.pbg_params['entity_path'] = \
|
|
185
|
+
os.path.join(filepath, "input/entity")
|
|
186
|
+
settings.pbg_params['edge_paths'] = \
|
|
187
|
+
[os.path.join(filepath, "input/edge"), ]
|
|
188
|
+
settings.pbg_params['entity_path'] = \
|
|
189
|
+
os.path.join(filepath, "input/entity")
|
|
190
|
+
if not os.path.exists(filepath):
|
|
191
|
+
os.makedirs(filepath)
|
|
192
|
+
if add_edge_weights is None:
|
|
193
|
+
if list_adata is None:
|
|
194
|
+
add_edge_weights = False
|
|
195
|
+
else:
|
|
196
|
+
add_edge_weights = True
|
|
197
|
+
def _get_df_edges(adj_mat, df_source, df_dest, adata, relation_id, include_weight = True, weight_scale = 1):
|
|
198
|
+
col_names = ["source", "relation", "destination"]
|
|
199
|
+
if include_weight:
|
|
200
|
+
col_names.append("weight")
|
|
201
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
202
|
+
df_edges_x['source'] = df_source.loc[
|
|
203
|
+
adata.obs_names[adj_mat.nonzero()[0]],
|
|
204
|
+
'alias'].values
|
|
205
|
+
df_edges_x['relation'] = relation_id
|
|
206
|
+
df_edges_x['destination'] = df_dest.loc[
|
|
207
|
+
adata.var_names[adj_mat.nonzero()[1]],
|
|
208
|
+
'alias'].values
|
|
209
|
+
if include_weight:
|
|
210
|
+
df_edges_x['weight'] = weight_scale
|
|
211
|
+
return(df_edges_x)
|
|
212
|
+
if list_adata is not None:
|
|
213
|
+
id_ent = pd.Index([]) # ids of all entities
|
|
214
|
+
dict_ent_type = dict()
|
|
215
|
+
ctr_ent = 0 # counter for entity types
|
|
216
|
+
entity_alias = pd.DataFrame(columns=['alias'])
|
|
217
|
+
dict_graph_stats = dict()
|
|
218
|
+
if add_edge_weights:
|
|
219
|
+
col_names = ["source", "relation", "destination", "weight"]
|
|
220
|
+
else:
|
|
221
|
+
col_names = ["source", "relation", "destination"]
|
|
222
|
+
df_edges = pd.DataFrame(columns=col_names)
|
|
223
|
+
settings.pbg_params['relations'] = []
|
|
224
|
+
if get_marker_significance and list_adata:
|
|
225
|
+
raise NotImplementedError("Marker gene significance is not yet implemented for graph generation from AnnData list.")
|
|
226
|
+
for ctr_rel, adata_ori in enumerate(list_adata):
|
|
227
|
+
obs_names = adata_ori.obs_names
|
|
228
|
+
var_names = adata_ori.var_names
|
|
229
|
+
if len(set(obs_names).intersection(id_ent)) == 0:
|
|
230
|
+
prefix_i = f'{prefix}{ctr_ent}'
|
|
231
|
+
id_ent = id_ent.union(adata_ori.obs_names)
|
|
232
|
+
entity_alias_obs = pd.DataFrame(
|
|
233
|
+
index=obs_names,
|
|
234
|
+
columns=['alias'],
|
|
235
|
+
data=[f'{prefix_i}.{x}'
|
|
236
|
+
for x in range(len(obs_names))])
|
|
237
|
+
settings.pbg_params['entities'][
|
|
238
|
+
prefix_i] = {'num_partitions': 1}
|
|
239
|
+
dict_ent_type[prefix_i] = obs_names
|
|
240
|
+
entity_alias = pd.concat(
|
|
241
|
+
[entity_alias, entity_alias_obs],
|
|
242
|
+
ignore_index=False)
|
|
243
|
+
obs_type = prefix_i
|
|
244
|
+
ctr_ent += 1
|
|
245
|
+
else:
|
|
246
|
+
for k, item in dict_ent_type.items():
|
|
247
|
+
if len(set(obs_names).intersection(item)) > 0:
|
|
248
|
+
obs_type = k
|
|
249
|
+
break
|
|
250
|
+
if not set(obs_names).issubset(id_ent):
|
|
251
|
+
id_ent = id_ent.union(adata_ori.obs_names)
|
|
252
|
+
adt_obs_names = list(set(obs_names)-set(item))
|
|
253
|
+
entity_alias_obs = pd.DataFrame(
|
|
254
|
+
index=adt_obs_names,
|
|
255
|
+
columns=['alias'],
|
|
256
|
+
data=[f'{prefix_i}.{len(item)+x}'
|
|
257
|
+
for x in range(len(adt_obs_names))])
|
|
258
|
+
dict_ent_type[obs_type] = obs_names.union(adt_obs_names)
|
|
259
|
+
entity_alias = pd.concat(
|
|
260
|
+
[entity_alias, entity_alias_obs],
|
|
261
|
+
ignore_index=False)
|
|
262
|
+
if len(set(var_names).intersection(id_ent)) == 0:
|
|
263
|
+
prefix_i = f'{prefix}{ctr_ent}'
|
|
264
|
+
id_ent = id_ent.union(adata_ori.var_names)
|
|
265
|
+
entity_alias_var = pd.DataFrame(
|
|
266
|
+
index=var_names,
|
|
267
|
+
columns=['alias'],
|
|
268
|
+
data=[f'{prefix_i}.{x}'
|
|
269
|
+
for x in range(len(var_names))])
|
|
270
|
+
settings.pbg_params['entities'][
|
|
271
|
+
prefix_i] = {'num_partitions': 1}
|
|
272
|
+
dict_ent_type[prefix_i] = var_names
|
|
273
|
+
entity_alias = pd.concat(
|
|
274
|
+
[entity_alias, entity_alias_var],
|
|
275
|
+
ignore_index=False)
|
|
276
|
+
var_type = prefix_i
|
|
277
|
+
ctr_ent += 1
|
|
278
|
+
else:
|
|
279
|
+
for k, item in dict_ent_type.items():
|
|
280
|
+
if len(set(var_names).intersection(item)) > 0:
|
|
281
|
+
var_type = k
|
|
282
|
+
break
|
|
283
|
+
if not set(var_names).issubset(id_ent):
|
|
284
|
+
id_ent = id_ent.union(adata_ori.var_names)
|
|
285
|
+
adt_var_names = list(set(var_names)-set(item))
|
|
286
|
+
entity_alias_var = pd.DataFrame(
|
|
287
|
+
index=adt_var_names,
|
|
288
|
+
columns=['alias'],
|
|
289
|
+
data=[f'{prefix_i}.{len(item)+x}'
|
|
290
|
+
for x in range(len(adt_var_names))])
|
|
291
|
+
dict_ent_type[var_type] = var_names.union(adt_var_names)
|
|
292
|
+
entity_alias = pd.concat(
|
|
293
|
+
[entity_alias, entity_alias_var],
|
|
294
|
+
ignore_index=False)
|
|
295
|
+
|
|
296
|
+
# generate edges
|
|
297
|
+
if layer is not None:
|
|
298
|
+
if layer in adata_ori.layers.keys():
|
|
299
|
+
arr_hge = adata_ori.layers[layer]
|
|
300
|
+
else:
|
|
301
|
+
print(f'`{layer}` does not exist in adata {ctr_rel} '
|
|
302
|
+
'in `list_adata`.`.X` is being used instead.')
|
|
303
|
+
arr_hge = adata_ori.X
|
|
304
|
+
else:
|
|
305
|
+
arr_hge = adata_ori.X
|
|
306
|
+
_row, _col = arr_hge.nonzero()
|
|
307
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
308
|
+
df_edges_x['source'] = entity_alias.loc[
|
|
309
|
+
obs_names[_row], 'alias'].values
|
|
310
|
+
df_edges_x['relation'] = f'r{ctr_rel}'
|
|
311
|
+
df_edges_x['destination'] = entity_alias.loc[
|
|
312
|
+
var_names[_col], 'alias'].values
|
|
313
|
+
if add_edge_weights:
|
|
314
|
+
df_edges_x['weight'] = \
|
|
315
|
+
arr_hge[_row, _col].A.flatten()
|
|
316
|
+
settings.pbg_params['relations'].append({
|
|
317
|
+
'name': f'r{ctr_rel}',
|
|
318
|
+
'lhs': f'{obs_type}',
|
|
319
|
+
'rhs': f'{var_type}',
|
|
320
|
+
'operator': 'none',
|
|
321
|
+
'weight': 1.0
|
|
322
|
+
})
|
|
323
|
+
dict_graph_stats[f'relation{ctr_rel}'] = {
|
|
324
|
+
'source': obs_type,
|
|
325
|
+
'destination': var_type,
|
|
326
|
+
'n_edges': df_edges_x.shape[0]}
|
|
327
|
+
print(
|
|
328
|
+
f'relation{ctr_rel}: '
|
|
329
|
+
f'source: {obs_type}, '
|
|
330
|
+
f'destination: {var_type}\n'
|
|
331
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
332
|
+
|
|
333
|
+
df_edges = pd.concat(
|
|
334
|
+
[df_edges, df_edges_x],
|
|
335
|
+
ignore_index=True)
|
|
336
|
+
adata_ori.obs['pbg_id'] = ""
|
|
337
|
+
adata_ori.var['pbg_id'] = ""
|
|
338
|
+
adata_ori.obs.loc[obs_names, 'pbg_id'] = \
|
|
339
|
+
entity_alias.loc[obs_names, 'alias'].copy()
|
|
340
|
+
adata_ori.var.loc[var_names, 'pbg_id'] = \
|
|
341
|
+
entity_alias.loc[var_names, 'alias'].copy()
|
|
342
|
+
|
|
343
|
+
else:
|
|
344
|
+
# Collect the indices of entities
|
|
345
|
+
dict_cells = dict() # unique cell indices from all anndata objects
|
|
346
|
+
ids_genes = pd.Index([])
|
|
347
|
+
ids_peaks = pd.Index([])
|
|
348
|
+
ids_kmers = pd.Index([])
|
|
349
|
+
ids_motifs = pd.Index([])
|
|
350
|
+
|
|
351
|
+
if list_CP is not None:
|
|
352
|
+
for adata_ori in list_CP:
|
|
353
|
+
if use_top_pcs_CP is None:
|
|
354
|
+
flag_top_pcs = use_top_pcs
|
|
355
|
+
else:
|
|
356
|
+
flag_top_pcs = use_top_pcs_CP
|
|
357
|
+
if flag_top_pcs:
|
|
358
|
+
adata = adata_ori[:, adata_ori.var['top_pcs']].copy()
|
|
359
|
+
else:
|
|
360
|
+
adata = adata_ori.copy()
|
|
361
|
+
ids_cells_i = adata.obs.index
|
|
362
|
+
if len(dict_cells) == 0:
|
|
363
|
+
dict_cells[prefix_C] = ids_cells_i
|
|
364
|
+
else:
|
|
365
|
+
# check if cell indices are included in dict_cells
|
|
366
|
+
flag_included = False
|
|
367
|
+
for k in dict_cells.keys():
|
|
368
|
+
ids_cells_k = dict_cells[k]
|
|
369
|
+
if set(ids_cells_i) <= set(ids_cells_k):
|
|
370
|
+
flag_included = True
|
|
371
|
+
break
|
|
372
|
+
if not flag_included:
|
|
373
|
+
# create a new set of entities
|
|
374
|
+
# when not all indices are included
|
|
375
|
+
dict_cells[
|
|
376
|
+
f'{prefix_C}{len(dict_cells)+1}'] = \
|
|
377
|
+
ids_cells_i
|
|
378
|
+
ids_peaks = ids_peaks.union(adata.var.index)
|
|
379
|
+
if get_marker_significance:
|
|
380
|
+
n_npeaks = min(int(len(ids_peaks)*fold_null_nodes), len(ids_peaks))
|
|
381
|
+
ids_npeaks = pd.Index([f'n{prefix_P}.{x}' for x in range(n_npeaks)])
|
|
382
|
+
if list_PM is not None:
|
|
383
|
+
for adata_ori in list_PM:
|
|
384
|
+
if use_top_pcs_PM is None:
|
|
385
|
+
flag_top_pcs = use_top_pcs
|
|
386
|
+
else:
|
|
387
|
+
flag_top_pcs = use_top_pcs_PM
|
|
388
|
+
if flag_top_pcs:
|
|
389
|
+
adata = adata_ori[:, adata_ori.var['top_pcs']].copy()
|
|
390
|
+
else:
|
|
391
|
+
adata = adata_ori.copy()
|
|
392
|
+
ids_peaks = ids_peaks.union(adata.obs.index)
|
|
393
|
+
ids_motifs = ids_motifs.union(adata.var.index)
|
|
394
|
+
if get_marker_significance:
|
|
395
|
+
n_nmotifs = int(len(ids_motifs)*fold_null_nodes)
|
|
396
|
+
ids_nmotifs = pd.Index([f'n{prefix_M}.{x}' for x in range(n_nmotifs)])
|
|
397
|
+
if list_PK is not None:
|
|
398
|
+
for adata_ori in list_PK:
|
|
399
|
+
if use_top_pcs_PK is None:
|
|
400
|
+
flag_top_pcs = use_top_pcs
|
|
401
|
+
else:
|
|
402
|
+
flag_top_pcs = use_top_pcs_PK
|
|
403
|
+
if flag_top_pcs:
|
|
404
|
+
adata = adata_ori[:, adata_ori.var['top_pcs']].copy()
|
|
405
|
+
else:
|
|
406
|
+
adata = adata_ori.copy()
|
|
407
|
+
ids_peaks = ids_peaks.union(adata.obs.index)
|
|
408
|
+
ids_kmers = ids_kmers.union(adata.var.index)
|
|
409
|
+
if get_marker_significance:
|
|
410
|
+
n_nkmers = int(len(ids_kmers)*fold_null_nodes)
|
|
411
|
+
ids_nkmers = pd.Index([f'n{prefix_K}.{x}' for x in range(n_nkmers)])
|
|
412
|
+
if list_CG is not None:
|
|
413
|
+
for adata_ori in list_CG:
|
|
414
|
+
if use_highly_variable:
|
|
415
|
+
adata = adata_ori[
|
|
416
|
+
:, adata_ori.var['highly_variable']].copy()
|
|
417
|
+
else:
|
|
418
|
+
adata = adata_ori.copy()
|
|
419
|
+
ids_cells_i = adata.obs.index
|
|
420
|
+
if len(dict_cells) == 0:
|
|
421
|
+
dict_cells[prefix_C] = ids_cells_i
|
|
422
|
+
else:
|
|
423
|
+
# check if cell indices are included in dict_cells
|
|
424
|
+
flag_included = False
|
|
425
|
+
for k in dict_cells.keys():
|
|
426
|
+
ids_cells_k = dict_cells[k]
|
|
427
|
+
if set(ids_cells_i) <= set(ids_cells_k):
|
|
428
|
+
flag_included = True
|
|
429
|
+
break
|
|
430
|
+
if not flag_included:
|
|
431
|
+
# create a new set of entities
|
|
432
|
+
# when not all indices are included
|
|
433
|
+
dict_cells[
|
|
434
|
+
f'{prefix_C}{len(dict_cells)+1}'] = \
|
|
435
|
+
ids_cells_i
|
|
436
|
+
ids_genes = ids_genes.union(adata.var.index)
|
|
437
|
+
if get_marker_significance:
|
|
438
|
+
n_ngenes = int(len(ids_genes)*fold_null_nodes)
|
|
439
|
+
ids_ngenes = pd.Index([f'n{prefix_G}.{x}' for x in range(n_ngenes)])
|
|
440
|
+
|
|
441
|
+
entity_alias = pd.DataFrame(columns=['alias'])
|
|
442
|
+
dict_df_cells = dict() # unique cell dataframes
|
|
443
|
+
for k in dict_cells.keys():
|
|
444
|
+
dict_df_cells[k] = pd.DataFrame(
|
|
445
|
+
index=dict_cells[k],
|
|
446
|
+
columns=['alias'],
|
|
447
|
+
data=[f'{k}.{x}' for x in range(len(dict_cells[k]))])
|
|
448
|
+
settings.pbg_params['entities'][k] = {'num_partitions': 1}
|
|
449
|
+
entity_alias = pd.concat(
|
|
450
|
+
[entity_alias, dict_df_cells[k]],
|
|
451
|
+
ignore_index=False)
|
|
452
|
+
if len(ids_genes) > 0:
|
|
453
|
+
df_genes = pd.DataFrame(
|
|
454
|
+
index=ids_genes,
|
|
455
|
+
columns=['alias'],
|
|
456
|
+
data=[f'{prefix_G}.{x}' for x in range(len(ids_genes))])
|
|
457
|
+
settings.pbg_params['entities'][prefix_G] = {'num_partitions': 1}
|
|
458
|
+
entity_alias = pd.concat(
|
|
459
|
+
[entity_alias, df_genes],
|
|
460
|
+
ignore_index=False)
|
|
461
|
+
if get_marker_significance and (len(ids_ngenes) > 0):
|
|
462
|
+
df_ngenes = pd.DataFrame(
|
|
463
|
+
index=ids_ngenes,
|
|
464
|
+
columns=['alias'],
|
|
465
|
+
data=ids_ngenes.tolist())
|
|
466
|
+
settings.pbg_params['entities'][f'n{prefix_G}'] = {'num_partitions': 1}
|
|
467
|
+
entity_alias = pd.concat([entity_alias, df_ngenes],
|
|
468
|
+
ignore_index=False)
|
|
469
|
+
if len(ids_peaks) > 0:
|
|
470
|
+
df_peaks = pd.DataFrame(
|
|
471
|
+
index=ids_peaks,
|
|
472
|
+
columns=['alias'],
|
|
473
|
+
data=[f'{prefix_P}.{x}' for x in range(len(ids_peaks))])
|
|
474
|
+
settings.pbg_params['entities'][prefix_P] = {'num_partitions': 1}
|
|
475
|
+
entity_alias = pd.concat(
|
|
476
|
+
[entity_alias, df_peaks],
|
|
477
|
+
ignore_index=False)
|
|
478
|
+
if get_marker_significance and (len(ids_npeaks) > 0):
|
|
479
|
+
df_npeaks = pd.DataFrame(
|
|
480
|
+
index=ids_npeaks,
|
|
481
|
+
columns=['alias'],
|
|
482
|
+
data=ids_npeaks.tolist())
|
|
483
|
+
settings.pbg_params['entities'][f'n{prefix_P}'] = {'num_partitions': 1}
|
|
484
|
+
entity_alias = pd.concat([entity_alias,df_npeaks],
|
|
485
|
+
ignore_index=False)
|
|
486
|
+
if len(ids_kmers) > 0:
|
|
487
|
+
df_kmers = pd.DataFrame(
|
|
488
|
+
index=ids_kmers,
|
|
489
|
+
columns=['alias'],
|
|
490
|
+
data=[f'{prefix_K}.{x}' for x in range(len(ids_kmers))])
|
|
491
|
+
settings.pbg_params['entities'][prefix_K] = {'num_partitions': 1}
|
|
492
|
+
entity_alias = pd.concat(
|
|
493
|
+
[entity_alias, df_kmers],
|
|
494
|
+
ignore_index=False)
|
|
495
|
+
if get_marker_significance and (len(ids_nkmers) > 0):
|
|
496
|
+
df_nkmers = pd.DataFrame(
|
|
497
|
+
index=ids_nkmers,
|
|
498
|
+
columns=['alias'],
|
|
499
|
+
data=ids_nkmers.tolist())
|
|
500
|
+
settings.pbg_params['entities'][f'n{prefix_K}'] = {'num_partitions': 1}
|
|
501
|
+
entity_alias = pd.concat([entity_alias,df_nkmers],
|
|
502
|
+
ignore_index=False)
|
|
503
|
+
if len(ids_motifs) > 0:
|
|
504
|
+
df_motifs = pd.DataFrame(
|
|
505
|
+
index=ids_motifs,
|
|
506
|
+
columns=['alias'],
|
|
507
|
+
data=[f'{prefix_M}.{x}' for x in range(len(ids_motifs))])
|
|
508
|
+
settings.pbg_params['entities'][prefix_M] = {'num_partitions': 1}
|
|
509
|
+
entity_alias = pd.concat(
|
|
510
|
+
[entity_alias, df_motifs],
|
|
511
|
+
ignore_index=False)
|
|
512
|
+
if get_marker_significance and (len(ids_nmotifs) > 0):
|
|
513
|
+
df_nmotifs = pd.DataFrame(
|
|
514
|
+
index=ids_nmotifs,
|
|
515
|
+
columns=['alias'],
|
|
516
|
+
data=ids_nmotifs.tolist())
|
|
517
|
+
settings.pbg_params['entities'][f'n{prefix_M}'] = {'num_partitions': 1}
|
|
518
|
+
entity_alias = pd.concat([entity_alias,df_nmotifs],
|
|
519
|
+
ignore_index=False)
|
|
520
|
+
# generate edges
|
|
521
|
+
dict_graph_stats = dict()
|
|
522
|
+
if add_edge_weights:
|
|
523
|
+
col_names = ["source", "relation", "destination", "weight"]
|
|
524
|
+
else:
|
|
525
|
+
col_names = ["source", "relation", "destination"]
|
|
526
|
+
df_edges = pd.DataFrame(columns=col_names)
|
|
527
|
+
id_r = 0
|
|
528
|
+
settings.pbg_params['relations'] = []
|
|
529
|
+
|
|
530
|
+
if list_CP is not None:
|
|
531
|
+
for i, adata_ori in enumerate(list_CP):
|
|
532
|
+
if use_top_pcs:
|
|
533
|
+
adata = adata_ori[:, adata_ori.var['top_pcs']].copy()
|
|
534
|
+
else:
|
|
535
|
+
adata = adata_ori.copy()
|
|
536
|
+
# select reference of cells
|
|
537
|
+
for key, df_cells in dict_df_cells.items():
|
|
538
|
+
if set(adata.obs_names) <= set(df_cells.index):
|
|
539
|
+
break
|
|
540
|
+
if layer is not None:
|
|
541
|
+
if layer in adata.layers.keys():
|
|
542
|
+
arr_hge = adata.layers[layer]
|
|
543
|
+
else:
|
|
544
|
+
print(f'`{layer}` does not exist in anndata {i} '
|
|
545
|
+
'in `list_CP`.`.X` is being used instead.')
|
|
546
|
+
arr_hge = adata.X
|
|
547
|
+
else:
|
|
548
|
+
arr_hge = adata.X
|
|
549
|
+
if get_marker_significance:
|
|
550
|
+
#n_npeaks = int(len(ids_peaks)*fold_null_nodes)
|
|
551
|
+
null_matrix = _randomize_matrix(arr_hge, n_npeaks, method='degPreserving')
|
|
552
|
+
null_adata = ad.AnnData(obs=adata.obs, var=df_npeaks, layers={"disc":null_matrix})
|
|
553
|
+
_row, _col = arr_hge.nonzero()
|
|
554
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
555
|
+
df_edges_x['source'] = df_cells.loc[
|
|
556
|
+
adata.obs_names[_row], 'alias'].values
|
|
557
|
+
df_edges_x['relation'] = f'r{id_r}'
|
|
558
|
+
df_edges_x['destination'] = df_peaks.loc[
|
|
559
|
+
adata.var_names[_col], 'alias'].values
|
|
560
|
+
if add_edge_weights:
|
|
561
|
+
df_edges_x['weight'] = \
|
|
562
|
+
arr_hge[_row, _col].A.flatten()
|
|
563
|
+
settings.pbg_params['relations'].append({
|
|
564
|
+
'name': f'r{id_r}',
|
|
565
|
+
'lhs': f'{key}',
|
|
566
|
+
'rhs': f'{prefix_P}',
|
|
567
|
+
'operator': 'none',
|
|
568
|
+
'weight': 1.0
|
|
569
|
+
})
|
|
570
|
+
dict_graph_stats[f'relation{id_r}'] = {
|
|
571
|
+
'source': key,
|
|
572
|
+
'destination': prefix_P,
|
|
573
|
+
'n_edges': df_edges_x.shape[0]}
|
|
574
|
+
print(
|
|
575
|
+
f'relation{id_r}: '
|
|
576
|
+
f'source: {key}, '
|
|
577
|
+
f'destination: {prefix_P}\n'
|
|
578
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
579
|
+
id_r += 1
|
|
580
|
+
df_edges = pd.concat(
|
|
581
|
+
[df_edges, df_edges_x],
|
|
582
|
+
ignore_index=True)
|
|
583
|
+
adata_ori.obs['pbg_id'] = ""
|
|
584
|
+
adata_ori.var['pbg_id'] = ""
|
|
585
|
+
adata_ori.obs.loc[adata.obs_names, 'pbg_id'] = \
|
|
586
|
+
df_cells.loc[adata.obs_names, 'alias'].copy()
|
|
587
|
+
adata_ori.var.loc[adata.var_names, 'pbg_id'] = \
|
|
588
|
+
df_peaks.loc[adata.var_names, 'alias'].copy()
|
|
589
|
+
if get_marker_significance:
|
|
590
|
+
_col, _row = null_matrix.transpose().nonzero()
|
|
591
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
592
|
+
df_edges_x['destination'] = df_cells.loc[
|
|
593
|
+
null_adata.obs_names[_row], 'alias'].values
|
|
594
|
+
df_edges_x['relation'] = f'r{id_r}'
|
|
595
|
+
df_edges_x['source'] = df_npeaks.loc[
|
|
596
|
+
null_adata.var_names[_col], 'alias'].values
|
|
597
|
+
df_edges_x['weight'] = \
|
|
598
|
+
null_matrix.transpose()[_col, _row].A.flatten()
|
|
599
|
+
settings.pbg_params['relations'].append({
|
|
600
|
+
'name': f'r{id_r}',
|
|
601
|
+
'lhs': f'n{prefix_P}',
|
|
602
|
+
'rhs': f'{key}',
|
|
603
|
+
'operator': 'fix',
|
|
604
|
+
'weight': 1.0,
|
|
605
|
+
})
|
|
606
|
+
print(
|
|
607
|
+
f'relation{id_r}: '
|
|
608
|
+
f'source: n{prefix_P}, '
|
|
609
|
+
f'destination: {key}\n'
|
|
610
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
611
|
+
dict_graph_stats[f'relation{id_r}'] = {
|
|
612
|
+
'source': f'n{prefix_P}',
|
|
613
|
+
'destination': key,
|
|
614
|
+
'n_edges': df_edges_x.shape[0]}
|
|
615
|
+
id_r += 1
|
|
616
|
+
df_edges = pd.concat(
|
|
617
|
+
[df_edges, df_edges_x],
|
|
618
|
+
ignore_index=True)
|
|
619
|
+
|
|
620
|
+
if list_PM is not None:
|
|
621
|
+
for i, adata_ori in enumerate(list_PM):
|
|
622
|
+
if use_top_pcs:
|
|
623
|
+
adata = adata_ori[:, adata_ori.var['top_pcs']].copy()
|
|
624
|
+
else:
|
|
625
|
+
adata = adata_ori.copy()
|
|
626
|
+
if layer is not None:
|
|
627
|
+
if layer in adata.layers.keys():
|
|
628
|
+
arr_hge = adata.layers[layer]
|
|
629
|
+
else:
|
|
630
|
+
print(f'`{layer}` does not exist in anndata {i} '
|
|
631
|
+
'in `list_PM`.`.X` is being used instead.')
|
|
632
|
+
arr_hge = adata.X
|
|
633
|
+
else:
|
|
634
|
+
arr_hge = adata.X
|
|
635
|
+
if get_marker_significance:
|
|
636
|
+
n_nmotifs = int(len(ids_motifs)*fold_null_nodes)
|
|
637
|
+
null_matrix = _randomize_matrix(arr_hge, n_nmotifs, method='degPreserving')
|
|
638
|
+
null_adata = ad.AnnData(obs=adata.obs, var=df_nmotifs, layers={"disc":null_matrix})
|
|
639
|
+
_row, _col = arr_hge.nonzero()
|
|
640
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
641
|
+
df_edges_x['source'] = df_peaks.loc[
|
|
642
|
+
adata.obs_names[_row], 'alias'].values
|
|
643
|
+
df_edges_x['relation'] = f'r{id_r}'
|
|
644
|
+
df_edges_x['destination'] = df_motifs.loc[
|
|
645
|
+
adata.var_names[_col], 'alias'].values
|
|
646
|
+
if add_edge_weights:
|
|
647
|
+
df_edges_x['weight'] = \
|
|
648
|
+
arr_hge[_row, _col].A.flatten()
|
|
649
|
+
settings.pbg_params['relations'].append({
|
|
650
|
+
'name': f'r{id_r}',
|
|
651
|
+
'lhs': f'{prefix_P}',
|
|
652
|
+
'rhs': f'{prefix_M}',
|
|
653
|
+
'operator': 'none',
|
|
654
|
+
'weight': 0.2
|
|
655
|
+
})
|
|
656
|
+
else:
|
|
657
|
+
settings.pbg_params['relations'].append({
|
|
658
|
+
'name': f'r{id_r}',
|
|
659
|
+
'lhs': f'{prefix_P}',
|
|
660
|
+
'rhs': f'{prefix_M}',
|
|
661
|
+
'operator': 'none',
|
|
662
|
+
'weight': 0.2
|
|
663
|
+
})
|
|
664
|
+
dict_graph_stats[f'relation{id_r}'] = {
|
|
665
|
+
'source': prefix_P,
|
|
666
|
+
'destination': prefix_M,
|
|
667
|
+
'n_edges': df_edges_x.shape[0]}
|
|
668
|
+
print(
|
|
669
|
+
f'relation{id_r}: '
|
|
670
|
+
f'source: {prefix_P}, '
|
|
671
|
+
f'destination: {prefix_M}\n'
|
|
672
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
673
|
+
|
|
674
|
+
id_r += 1
|
|
675
|
+
df_edges = pd.concat(
|
|
676
|
+
[df_edges, df_edges_x],
|
|
677
|
+
ignore_index=True)
|
|
678
|
+
adata_ori.obs['pbg_id'] = ""
|
|
679
|
+
adata_ori.var['pbg_id'] = ""
|
|
680
|
+
adata_ori.obs.loc[adata.obs_names, 'pbg_id'] = \
|
|
681
|
+
df_peaks.loc[adata.obs_names, 'alias'].copy()
|
|
682
|
+
adata_ori.var.loc[adata.var_names, 'pbg_id'] = \
|
|
683
|
+
df_motifs.loc[adata.var_names, 'alias'].copy()
|
|
684
|
+
if get_marker_significance:
|
|
685
|
+
_col, _row = null_matrix.transpose().nonzero()
|
|
686
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
687
|
+
df_edges_x['destination'] = df_peaks.loc[
|
|
688
|
+
null_adata.obs_names[_row], 'alias'].values
|
|
689
|
+
df_edges_x['relation'] = f'r{id_r}'
|
|
690
|
+
df_edges_x['source'] = df_nmotifs.loc[
|
|
691
|
+
null_adata.var_names[_col], 'alias'].values
|
|
692
|
+
df_edges_x['weight'] = \
|
|
693
|
+
null_matrix.transpose()[_col, _row].A.flatten()
|
|
694
|
+
settings.pbg_params['relations'].append({
|
|
695
|
+
'name': f'r{id_r}',
|
|
696
|
+
'lhs': f'n{prefix_M}',
|
|
697
|
+
'rhs': f'{prefix_P}',
|
|
698
|
+
'operator': 'fix',
|
|
699
|
+
'weight': 1.0,
|
|
700
|
+
})
|
|
701
|
+
print(
|
|
702
|
+
f'relation{id_r}: '
|
|
703
|
+
f'source: n{prefix_M}, '
|
|
704
|
+
f'destination: {prefix_P}\n'
|
|
705
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
706
|
+
dict_graph_stats[f'relation{id_r}'] = {
|
|
707
|
+
'source': f'n{prefix_M}',
|
|
708
|
+
'destination': prefix_P,
|
|
709
|
+
'n_edges': df_edges_x.shape[0]}
|
|
710
|
+
id_r += 1
|
|
711
|
+
df_edges = pd.concat(
|
|
712
|
+
[df_edges, df_edges_x],
|
|
713
|
+
ignore_index=True)
|
|
714
|
+
|
|
715
|
+
if list_PK is not None:
|
|
716
|
+
for i, adata_ori in enumerate(list_PK):
|
|
717
|
+
if use_top_pcs:
|
|
718
|
+
adata = adata_ori[:, adata_ori.var['top_pcs']].copy()
|
|
719
|
+
else:
|
|
720
|
+
adata = adata_ori.copy()
|
|
721
|
+
if layer is not None:
|
|
722
|
+
if layer in adata.layers.keys():
|
|
723
|
+
arr_hge = adata.layers[layer]
|
|
724
|
+
else:
|
|
725
|
+
print(f'`{layer}` does not exist in anndata {i} '
|
|
726
|
+
'in `list_PK`.`.X` is being used instead.')
|
|
727
|
+
arr_hge = adata.X
|
|
728
|
+
else:
|
|
729
|
+
arr_hge = adata.X
|
|
730
|
+
if get_marker_significance:
|
|
731
|
+
n_nkmers = int(len(ids_kmers)*fold_null_nodes)
|
|
732
|
+
null_matrix = _randomize_matrix(arr_hge, n_nkmers, method='degPreserving')
|
|
733
|
+
null_adata = ad.AnnData(obs=adata.obs, var=df_nkmers, layers={"disc":null_matrix})
|
|
734
|
+
_row, _col = arr_hge.nonzero()
|
|
735
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
736
|
+
df_edges_x['source'] = df_peaks.loc[
|
|
737
|
+
adata.obs_names[_row], 'alias'].values
|
|
738
|
+
df_edges_x['relation'] = f'r{id_r}'
|
|
739
|
+
df_edges_x['destination'] = df_kmers.loc[
|
|
740
|
+
adata.var_names[_col], 'alias'].values
|
|
741
|
+
if add_edge_weights:
|
|
742
|
+
df_edges_x['weight'] = \
|
|
743
|
+
arr_hge[_row, _col].A.flatten()
|
|
744
|
+
settings.pbg_params['relations'].append({
|
|
745
|
+
'name': f'r{id_r}',
|
|
746
|
+
'lhs': f'{prefix_P}',
|
|
747
|
+
'rhs': f'{prefix_K}',
|
|
748
|
+
'operator': 'none',
|
|
749
|
+
'weight': 0.02
|
|
750
|
+
})
|
|
751
|
+
else:
|
|
752
|
+
settings.pbg_params['relations'].append({
|
|
753
|
+
'name': f'r{id_r}',
|
|
754
|
+
'lhs': f'{prefix_P}',
|
|
755
|
+
'rhs': f'{prefix_K}',
|
|
756
|
+
'operator': 'none',
|
|
757
|
+
'weight': 0.02
|
|
758
|
+
})
|
|
759
|
+
print(
|
|
760
|
+
f'relation{id_r}: '
|
|
761
|
+
f'source: {prefix_P}, '
|
|
762
|
+
f'destination: {prefix_K}\n'
|
|
763
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
764
|
+
dict_graph_stats[f'relation{id_r}'] = {
|
|
765
|
+
'source': prefix_P,
|
|
766
|
+
'destination': prefix_K,
|
|
767
|
+
'n_edges': df_edges_x.shape[0]}
|
|
768
|
+
|
|
769
|
+
id_r += 1
|
|
770
|
+
df_edges = pd.concat(
|
|
771
|
+
[df_edges, df_edges_x],
|
|
772
|
+
ignore_index=True)
|
|
773
|
+
adata_ori.obs['pbg_id'] = ""
|
|
774
|
+
adata_ori.var['pbg_id'] = ""
|
|
775
|
+
adata_ori.obs.loc[adata.obs_names, 'pbg_id'] = \
|
|
776
|
+
df_peaks.loc[adata.obs_names, 'alias'].copy()
|
|
777
|
+
adata_ori.var.loc[adata.var_names, 'pbg_id'] = \
|
|
778
|
+
df_kmers.loc[adata.var_names, 'alias'].copy()
|
|
779
|
+
if get_marker_significance:
|
|
780
|
+
_col, _row = null_matrix.transpose().nonzero()
|
|
781
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
782
|
+
df_edges_x['destination'] = df_peaks.loc[
|
|
783
|
+
null_adata.obs_names[_row], 'alias'].values
|
|
784
|
+
df_edges_x['relation'] = f'r{id_r}'
|
|
785
|
+
df_edges_x['source'] = df_nkmers.loc[
|
|
786
|
+
null_adata.var_names[_col], 'alias'].values
|
|
787
|
+
df_edges_x['weight'] = \
|
|
788
|
+
null_matrix.transpose()[_col, _row].A.flatten()
|
|
789
|
+
settings.pbg_params['relations'].append({
|
|
790
|
+
'name': f'r{id_r}',
|
|
791
|
+
'lhs': f'n{prefix_K}',
|
|
792
|
+
'rhs': f'{prefix_P}',
|
|
793
|
+
'operator': 'fix',
|
|
794
|
+
'weight': 0.02,
|
|
795
|
+
})
|
|
796
|
+
print(
|
|
797
|
+
f'relation{id_r}: '
|
|
798
|
+
f'source: n{prefix_K}, '
|
|
799
|
+
f'destination: {prefix_P}\n'
|
|
800
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
801
|
+
dict_graph_stats[f'relation{id_r}'] = {
|
|
802
|
+
'source': f'n{prefix_K}',
|
|
803
|
+
'destination': prefix_P,
|
|
804
|
+
'n_edges': df_edges_x.shape[0]}
|
|
805
|
+
id_r += 1
|
|
806
|
+
df_edges = pd.concat(
|
|
807
|
+
[df_edges, df_edges_x],
|
|
808
|
+
ignore_index=True)
|
|
809
|
+
|
|
810
|
+
if list_CG is not None:
|
|
811
|
+
for i, adata_ori in enumerate(list_CG):
|
|
812
|
+
if use_highly_variable:
|
|
813
|
+
adata = adata_ori[
|
|
814
|
+
:, adata_ori.var['highly_variable']].copy()
|
|
815
|
+
else:
|
|
816
|
+
adata = adata_ori.copy()
|
|
817
|
+
# select reference of cells
|
|
818
|
+
for key, df_cells in dict_df_cells.items():
|
|
819
|
+
if set(adata.obs_names) <= set(df_cells.index):
|
|
820
|
+
break
|
|
821
|
+
if layer is not None:
|
|
822
|
+
if layer in adata.layers.keys():
|
|
823
|
+
arr_hge = adata.layers[layer]
|
|
824
|
+
else:
|
|
825
|
+
print(f'`{layer}` does not exist in anndata {i} '
|
|
826
|
+
'in `list_CG`.`.X` is being used instead.')
|
|
827
|
+
arr_hge = adata.X
|
|
828
|
+
else:
|
|
829
|
+
arr_hge = adata.X
|
|
830
|
+
if get_marker_significance:
|
|
831
|
+
n_ngenes = int(len(ids_genes)*fold_null_nodes)
|
|
832
|
+
null_exp_matrix = _randomize_matrix(arr_hge, n_ngenes, method='degPreserving')
|
|
833
|
+
null_adata = ad.AnnData(obs=adata.obs, var=df_ngenes, layers={"disc":null_exp_matrix})
|
|
834
|
+
if add_edge_weights:
|
|
835
|
+
_row, _col = arr_hge.nonzero()
|
|
836
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
837
|
+
df_edges_x['source'] = df_cells.loc[
|
|
838
|
+
adata.obs_names[_row], 'alias'].values
|
|
839
|
+
df_edges_x['relation'] = f'r{id_r}'
|
|
840
|
+
df_edges_x['destination'] = df_genes.loc[
|
|
841
|
+
adata.var_names[_col], 'alias'].values
|
|
842
|
+
df_edges_x['weight'] = \
|
|
843
|
+
arr_hge[_row, _col].A.flatten()
|
|
844
|
+
settings.pbg_params['relations'].append({
|
|
845
|
+
'name': f'r{id_r}',
|
|
846
|
+
'lhs': f'{key}',
|
|
847
|
+
'rhs': f'{prefix_G}',
|
|
848
|
+
'operator': 'none',
|
|
849
|
+
'weight': 1.0,
|
|
850
|
+
})
|
|
851
|
+
print(
|
|
852
|
+
f'relation{id_r}: '
|
|
853
|
+
f'source: {key}, '
|
|
854
|
+
f'destination: {prefix_G}\n'
|
|
855
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
856
|
+
dict_graph_stats[f'relation{id_r}'] = {
|
|
857
|
+
'source': key,
|
|
858
|
+
'destination': prefix_G,
|
|
859
|
+
'n_edges': df_edges_x.shape[0]}
|
|
860
|
+
id_r += 1
|
|
861
|
+
df_edges = pd.concat(
|
|
862
|
+
[df_edges, df_edges_x],
|
|
863
|
+
ignore_index=True)
|
|
864
|
+
if get_marker_significance:
|
|
865
|
+
_col, _row = null_exp_matrix.transpose().nonzero()
|
|
866
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
867
|
+
df_edges_x['destination'] = df_cells.loc[
|
|
868
|
+
null_adata.obs_names[_row], 'alias'].values
|
|
869
|
+
df_edges_x['relation'] = f'r{id_r}'
|
|
870
|
+
df_edges_x['source'] = df_ngenes.loc[
|
|
871
|
+
null_adata.var_names[_col], 'alias'].values
|
|
872
|
+
df_edges_x['weight'] = \
|
|
873
|
+
null_exp_matrix.transpose()[_col, _row].A.flatten()
|
|
874
|
+
settings.pbg_params['relations'].append({
|
|
875
|
+
'name': f'r{id_r}',
|
|
876
|
+
'lhs': f'n{prefix_G}',
|
|
877
|
+
'rhs': f'{key}',
|
|
878
|
+
'operator': 'fix',
|
|
879
|
+
'weight': 1.0,
|
|
880
|
+
})
|
|
881
|
+
print(
|
|
882
|
+
f'relation{id_r}: '
|
|
883
|
+
f'source: n{prefix_G}, '
|
|
884
|
+
f'destination: {key}\n'
|
|
885
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
886
|
+
dict_graph_stats[f'relation{id_r}'] = {
|
|
887
|
+
'source': f'n{prefix_G}',
|
|
888
|
+
'destination': key,
|
|
889
|
+
'n_edges': df_edges_x.shape[0]}
|
|
890
|
+
id_r += 1
|
|
891
|
+
df_edges = pd.concat(
|
|
892
|
+
[df_edges, df_edges_x],
|
|
893
|
+
ignore_index=True)
|
|
894
|
+
else:
|
|
895
|
+
expr_level = np.unique(arr_hge.data)
|
|
896
|
+
expr_weight = np.linspace(
|
|
897
|
+
start=1, stop=5, num=len(expr_level))
|
|
898
|
+
for i_lvl, lvl in enumerate(expr_level):
|
|
899
|
+
_row, _col = (arr_hge == lvl).astype(int).nonzero()
|
|
900
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
901
|
+
df_edges_x['source'] = df_cells.loc[
|
|
902
|
+
adata.obs_names[_row], 'alias'].values
|
|
903
|
+
df_edges_x['relation'] = f'r{id_r}'
|
|
904
|
+
df_edges_x['destination'] = df_genes.loc[
|
|
905
|
+
adata.var_names[_col], 'alias'].values
|
|
906
|
+
settings.pbg_params['relations'].append({
|
|
907
|
+
'name': f'r{id_r}',
|
|
908
|
+
'lhs': f'{key}',
|
|
909
|
+
'rhs': f'{prefix_G}',
|
|
910
|
+
'operator': 'none',
|
|
911
|
+
'weight': round(expr_weight[i_lvl], 2),
|
|
912
|
+
})
|
|
913
|
+
print(
|
|
914
|
+
f'relation{id_r}: '
|
|
915
|
+
f'source: {key}, '
|
|
916
|
+
f'destination: {prefix_G}\n'
|
|
917
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
918
|
+
dict_graph_stats[f'relation{id_r}'] = {
|
|
919
|
+
'source': key,
|
|
920
|
+
'destination': prefix_G,
|
|
921
|
+
'n_edges': df_edges_x.shape[0]}
|
|
922
|
+
id_r += 1
|
|
923
|
+
df_edges = pd.concat(
|
|
924
|
+
[df_edges, df_edges_x], ignore_index=True)
|
|
925
|
+
if get_marker_significance:
|
|
926
|
+
# generate null AnnData with cells x null genes
|
|
927
|
+
df_edges_v = _get_df_edges((null_exp_matrix == lvl).astype(int).T,
|
|
928
|
+
df_ngenes, df_cells, null_adata.transpose(), f'r{id_r}', include_weight=True, weight_scale=lvl)
|
|
929
|
+
print(f'relation{id_r}: '
|
|
930
|
+
f'source: n{prefix_G}, '
|
|
931
|
+
f'destination: {key}\n'
|
|
932
|
+
f'#edges: {df_edges_v.shape[0]}')
|
|
933
|
+
dict_graph_stats[f'relation{id_r}'] = \
|
|
934
|
+
{'source': f'n{prefix_G}',
|
|
935
|
+
'destination': key,
|
|
936
|
+
'n_edges': df_edges_v.shape[0]}
|
|
937
|
+
df_edges = pd.concat([df_edges, df_edges_v],
|
|
938
|
+
ignore_index=True)
|
|
939
|
+
settings.pbg_params['relations'].append(
|
|
940
|
+
{'name': f'r{id_r}',
|
|
941
|
+
'lhs': f'n{prefix_G}',
|
|
942
|
+
'rhs': f'{key}',
|
|
943
|
+
'operator': 'fix',
|
|
944
|
+
'weight': round(expr_weight[i_lvl], 2),
|
|
945
|
+
})
|
|
946
|
+
id_r += 1
|
|
947
|
+
|
|
948
|
+
adata_ori.obs['pbg_id'] = ""
|
|
949
|
+
adata_ori.var['pbg_id'] = ""
|
|
950
|
+
adata_ori.obs.loc[adata.obs_names, 'pbg_id'] = \
|
|
951
|
+
df_cells.loc[adata.obs_names, 'alias'].copy()
|
|
952
|
+
adata_ori.var.loc[adata.var_names, 'pbg_id'] = \
|
|
953
|
+
df_genes.loc[adata.var_names, 'alias'].copy()
|
|
954
|
+
|
|
955
|
+
if list_CC is not None:
|
|
956
|
+
for i, adata in enumerate(list_CC):
|
|
957
|
+
# select reference of cells
|
|
958
|
+
for key_obs, df_cells_obs in dict_df_cells.items():
|
|
959
|
+
if set(adata.obs_names) <= set(df_cells_obs.index):
|
|
960
|
+
break
|
|
961
|
+
for key_var, df_cells_var in dict_df_cells.items():
|
|
962
|
+
if set(adata.var_names) <= set(df_cells_var.index):
|
|
963
|
+
break
|
|
964
|
+
if layer is not None:
|
|
965
|
+
if layer in adata.layers.keys():
|
|
966
|
+
arr_hge = adata.layers[layer]
|
|
967
|
+
else:
|
|
968
|
+
print(f'`{layer}` does not exist in anndata {i} '
|
|
969
|
+
'in `list_PM`.`.X` is being used instead.')
|
|
970
|
+
arr_hge = adata.X
|
|
971
|
+
else:
|
|
972
|
+
arr_hge = adata.X
|
|
973
|
+
_row, _col = arr_hge.nonzero()
|
|
974
|
+
# edges between ref and query
|
|
975
|
+
df_edges_x = pd.DataFrame(columns=col_names)
|
|
976
|
+
df_edges_x['source'] = df_cells_obs.loc[
|
|
977
|
+
adata.obs_names[_row], 'alias'].values
|
|
978
|
+
df_edges_x['relation'] = f'r{id_r}'
|
|
979
|
+
df_edges_x['destination'] = df_cells_var.loc[
|
|
980
|
+
adata.var_names[_col], 'alias'].values
|
|
981
|
+
if add_edge_weights:
|
|
982
|
+
df_edges_x['weight'] = \
|
|
983
|
+
arr_hge[_row, _col].A.flatten()
|
|
984
|
+
settings.pbg_params['relations'].append({
|
|
985
|
+
'name': f'r{id_r}',
|
|
986
|
+
'lhs': f'{key_obs}',
|
|
987
|
+
'rhs': f'{key_var}',
|
|
988
|
+
'operator': 'none',
|
|
989
|
+
'weight': 1.0
|
|
990
|
+
})
|
|
991
|
+
else:
|
|
992
|
+
settings.pbg_params['relations'].append({
|
|
993
|
+
'name': f'r{id_r}',
|
|
994
|
+
'lhs': f'{key_obs}',
|
|
995
|
+
'rhs': f'{key_var}',
|
|
996
|
+
'operator': 'none',
|
|
997
|
+
'weight': 10.0
|
|
998
|
+
})
|
|
999
|
+
print(
|
|
1000
|
+
f'relation{id_r}: '
|
|
1001
|
+
f'source: {key_obs}, '
|
|
1002
|
+
f'destination: {key_var}\n'
|
|
1003
|
+
f'#edges: {df_edges_x.shape[0]}')
|
|
1004
|
+
dict_graph_stats[f'relation{id_r}'] = {
|
|
1005
|
+
'source': key_obs,
|
|
1006
|
+
'destination': key_var,
|
|
1007
|
+
'n_edges': df_edges_x.shape[0]}
|
|
1008
|
+
|
|
1009
|
+
id_r += 1
|
|
1010
|
+
df_edges = pd.concat(
|
|
1011
|
+
[df_edges, df_edges_x],
|
|
1012
|
+
ignore_index=True)
|
|
1013
|
+
adata.obs['pbg_id'] = df_cells_obs.loc[
|
|
1014
|
+
adata.obs_names, 'alias'].copy()
|
|
1015
|
+
adata.var['pbg_id'] = df_cells_var.loc[
|
|
1016
|
+
adata.var_names, 'alias'].copy()
|
|
1017
|
+
|
|
1018
|
+
print(f'Total number of edges: {df_edges.shape[0]}')
|
|
1019
|
+
dict_graph_stats['n_edges'] = df_edges.shape[0]
|
|
1020
|
+
settings.graph_stats[dirname] = dict_graph_stats
|
|
1021
|
+
|
|
1022
|
+
print(f'Writing graph file "pbg_graph.txt" to "{filepath}" ...')
|
|
1023
|
+
df_edges.to_csv(os.path.join(filepath, "pbg_graph.txt"),
|
|
1024
|
+
header=False,
|
|
1025
|
+
index=False,
|
|
1026
|
+
sep='\t')
|
|
1027
|
+
entity_alias.to_csv(os.path.join(filepath, 'entity_alias.txt'),
|
|
1028
|
+
header=True,
|
|
1029
|
+
index=True,
|
|
1030
|
+
sep='\t')
|
|
1031
|
+
with open(os.path.join(filepath, 'graph_stats.json'), 'w') as fp:
|
|
1032
|
+
json.dump(dict_graph_stats,
|
|
1033
|
+
fp,
|
|
1034
|
+
sort_keys=True,
|
|
1035
|
+
indent=4,
|
|
1036
|
+
separators=(',', ': '))
|
|
1037
|
+
print("Finished.")
|
|
1038
|
+
settings.graph_stats[dirname]['entities'] = settings.pbg_params['entities']
|
|
1039
|
+
settings.graph_stats[dirname]['relations'] = settings.pbg_params['relations']
|
|
1040
|
+
if get_marker_significance:
|
|
1041
|
+
filepath = os.path.join(settings.workdir, 'pbg', dirname_orig)
|
|
1042
|
+
settings.pbg_params['entity_path'] = \
|
|
1043
|
+
os.path.join(filepath, "input/entity")
|
|
1044
|
+
settings.pbg_params['edge_paths'] = \
|
|
1045
|
+
[os.path.join(filepath, "input/edge"), ]
|
|
1046
|
+
settings.pbg_params['entities'] = settings.graph_stats[dirname_orig]['entities']
|
|
1047
|
+
settings.pbg_params['relations'] = settings.graph_stats[dirname_orig]['relations']
|
|
1048
|
+
if copy:
|
|
1049
|
+
return df_edges
|
|
1050
|
+
else:
|
|
1051
|
+
return None
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
def pbg_train(dirname=None,
|
|
1055
|
+
pbg_params=None,
|
|
1056
|
+
output='model',
|
|
1057
|
+
auto_wd=True,
|
|
1058
|
+
save_wd=False,
|
|
1059
|
+
use_edge_weights=False,
|
|
1060
|
+
get_marker_significance=False,):
|
|
1061
|
+
"""PBG training
|
|
1062
|
+
|
|
1063
|
+
Parameters
|
|
1064
|
+
----------
|
|
1065
|
+
dirname: `str`, optional (default: None)
|
|
1066
|
+
The name of the directory in which graph is stored
|
|
1067
|
+
If None, it will be inferred from `pbg_params['entity_path']`
|
|
1068
|
+
pbg_params: `dict`, optional (default: None)
|
|
1069
|
+
Configuration for pbg training.
|
|
1070
|
+
If specified, it will be used instead of the default setting
|
|
1071
|
+
output: `str`, optional (default: 'model')
|
|
1072
|
+
The name of the directory where training output will be written to.
|
|
1073
|
+
It overrides `pbg_params` if `checkpoint_path` is specified in it
|
|
1074
|
+
auto_wd: `bool`, optional (default: True)
|
|
1075
|
+
If True, it will override `pbg_params['wd']` with a new weight decay
|
|
1076
|
+
estimated based on training sample size
|
|
1077
|
+
Recommended for relative small training sample size (<1e7)
|
|
1078
|
+
save_wd: `bool`, optional (default: False)
|
|
1079
|
+
If True, estimated `wd` will be saved to `settings.pbg_params['wd']`
|
|
1080
|
+
use_edge_weights: `bool`, optional (default: False)
|
|
1081
|
+
If True, the edge weights are used for the training;
|
|
1082
|
+
If False, the weights of relation types are used instead,
|
|
1083
|
+
and edge weights will be ignored.
|
|
1084
|
+
|
|
1085
|
+
Returns
|
|
1086
|
+
-------
|
|
1087
|
+
updates `settings.pbg_params` with the following parameter
|
|
1088
|
+
checkpoint_path:
|
|
1089
|
+
The path to the directory where checkpoints (and thus the output)
|
|
1090
|
+
will be written to.
|
|
1091
|
+
If checkpoints are found in it, training will resume from them.
|
|
1092
|
+
"""
|
|
1093
|
+
if pbg_params is None:
|
|
1094
|
+
pbg_params = settings.pbg_params.copy()
|
|
1095
|
+
else:
|
|
1096
|
+
assert isinstance(pbg_params, dict),\
|
|
1097
|
+
"`pbg_params` must be dict"
|
|
1098
|
+
|
|
1099
|
+
if dirname is None:
|
|
1100
|
+
filepath = Path(pbg_params['entity_path']).parent.parent.as_posix()
|
|
1101
|
+
dirname = os.path.basename(filepath)
|
|
1102
|
+
else:
|
|
1103
|
+
filepath = os.path.join(settings.workdir, 'pbg', dirname)
|
|
1104
|
+
pbg_params['checkpoint_path'] = os.path.join(filepath, output)
|
|
1105
|
+
settings.pbg_params['checkpoint_path'] = pbg_params['checkpoint_path']
|
|
1106
|
+
if get_marker_significance:
|
|
1107
|
+
pbg_train(dirname=dirname,
|
|
1108
|
+
pbg_params=pbg_params,
|
|
1109
|
+
output=output,
|
|
1110
|
+
auto_wd=auto_wd,
|
|
1111
|
+
save_wd=True,
|
|
1112
|
+
use_edge_weights=use_edge_weights,
|
|
1113
|
+
get_marker_significance=False)
|
|
1114
|
+
pbg_params = pbg_params.copy()
|
|
1115
|
+
n_edges = settings.graph_stats[
|
|
1116
|
+
os.path.basename(filepath)]['n_edges']
|
|
1117
|
+
filepath += "_with_sig"
|
|
1118
|
+
pbg_params['checkpoint_path'] = os.path.join(filepath, output)
|
|
1119
|
+
pbg_params['entity_path'] = os.path.join(filepath, "input/entity")
|
|
1120
|
+
pbg_params['edge_paths'] = [os.path.join(filepath, "input/edge"), ]
|
|
1121
|
+
pbg_params['relations'] = settings.graph_stats[dirname + "_with_sig"]['relations']
|
|
1122
|
+
auto_wd = False
|
|
1123
|
+
pbg_params['wd'] = settings.pbg_params['wd'] * n_edges / settings.graph_stats[
|
|
1124
|
+
os.path.basename(filepath)]['n_edges']
|
|
1125
|
+
settings.pbg_params['wd'] = pbg_params['wd']
|
|
1126
|
+
|
|
1127
|
+
if auto_wd:
|
|
1128
|
+
# empirical numbers from simulation experiments
|
|
1129
|
+
if settings.graph_stats[
|
|
1130
|
+
os.path.basename(filepath)]['n_edges'] < 5e7:
|
|
1131
|
+
# optimial wd (0.013) for sample size (2725781)
|
|
1132
|
+
wd = 0.013 * 2725781 / settings.graph_stats[
|
|
1133
|
+
os.path.basename(filepath)]['n_edges']
|
|
1134
|
+
else:
|
|
1135
|
+
# optimial wd (0.0004) for sample size (59103481)
|
|
1136
|
+
wd = 0.0004 * 59103481 / settings.graph_stats[
|
|
1137
|
+
os.path.basename(filepath)]['n_edges']
|
|
1138
|
+
print(f'Auto-estimated weight decay is {wd:.6E}')
|
|
1139
|
+
pbg_params['wd'] = wd
|
|
1140
|
+
if save_wd:
|
|
1141
|
+
settings.pbg_params['wd'] = pbg_params['wd']
|
|
1142
|
+
print(f"`.settings.pbg_params['wd']` has been updated to {wd:.6E}")
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
# to avoid oversubscription issues in workloads
|
|
1146
|
+
# that involve nested parallelism
|
|
1147
|
+
os.environ["OMP_NUM_THREADS"] = "1"
|
|
1148
|
+
|
|
1149
|
+
loader = ConfigFileLoader()
|
|
1150
|
+
config = loader.load_config_simba(pbg_params)
|
|
1151
|
+
set_logging_verbosity(config.verbose)
|
|
1152
|
+
|
|
1153
|
+
list_filenames = [os.path.join(filepath, "pbg_graph.txt")]
|
|
1154
|
+
input_edge_paths = [Path(name) for name in list_filenames]
|
|
1155
|
+
print("Converting input data ...")
|
|
1156
|
+
if use_edge_weights:
|
|
1157
|
+
print("Edge weights are being used ...")
|
|
1158
|
+
convert_input_data(
|
|
1159
|
+
config.entities,
|
|
1160
|
+
config.relations,
|
|
1161
|
+
config.entity_path,
|
|
1162
|
+
config.edge_paths,
|
|
1163
|
+
input_edge_paths,
|
|
1164
|
+
TSVEdgelistReader(lhs_col=0, rhs_col=2, rel_col=1, weight_col=3),
|
|
1165
|
+
dynamic_relations=config.dynamic_relations,
|
|
1166
|
+
)
|
|
1167
|
+
else:
|
|
1168
|
+
convert_input_data(
|
|
1169
|
+
config.entities,
|
|
1170
|
+
config.relations,
|
|
1171
|
+
config.entity_path,
|
|
1172
|
+
config.edge_paths,
|
|
1173
|
+
input_edge_paths,
|
|
1174
|
+
TSVEdgelistReader(lhs_col=0, rhs_col=2, rel_col=1),
|
|
1175
|
+
dynamic_relations=config.dynamic_relations,
|
|
1176
|
+
)
|
|
1177
|
+
subprocess_init = SubprocessInitializer()
|
|
1178
|
+
subprocess_init.register(setup_logging, config.verbose)
|
|
1179
|
+
subprocess_init.register(add_to_sys_path, loader.config_dir.name)
|
|
1180
|
+
|
|
1181
|
+
train_config = attr.evolve(config, edge_paths=config.edge_paths)
|
|
1182
|
+
print("Starting training ...")
|
|
1183
|
+
train(train_config, subprocess_init=subprocess_init)
|
|
1184
|
+
print("Finished")
|