Sanjana Vekhande commited on
Commit ·
cbddf96
1
Parent(s): 01de07f
Fix gene parsing and apply expression mappings
Browse files- utils/bootstrap_genes.py +38 -23
utils/bootstrap_genes.py
CHANGED
|
@@ -16,6 +16,23 @@ def extract_genes_from_gpa(gpa_str):
|
|
| 16 |
keywords = {'or', 'and', 'not'}
|
| 17 |
return [t for t in tokens if t.lower() not in keywords]
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
def read_combined_geneExpr(combined_geneExpr_filename):
|
| 20 |
if not os.path.isfile(combined_geneExpr_filename):
|
| 21 |
raise FileNotFoundError(f"Missing combined normalized count file, expected at {combined_geneExpr_filename}")
|
|
@@ -28,13 +45,11 @@ def is_real_gene_with_mapping(gene):
|
|
| 28 |
def read_system_gene(model_pre_filename):
|
| 29 |
rxn_df = read_model_excel(model_pre_filename, "Reactions")
|
| 30 |
|
| 31 |
-
# Support
|
| 32 |
if "genes" in rxn_df.columns:
|
| 33 |
gene_col = "genes"
|
| 34 |
-
use_ast = True
|
| 35 |
elif "gpaAssociation" in rxn_df.columns:
|
| 36 |
gene_col = "gpaAssociation"
|
| 37 |
-
use_ast = False
|
| 38 |
else:
|
| 39 |
raise ValueError(
|
| 40 |
"Reactions sheet must have a 'genes' or 'gpaAssociation' column — "
|
|
@@ -45,10 +60,7 @@ def read_system_gene(model_pre_filename):
|
|
| 45 |
missing_gene_system_dict = {}
|
| 46 |
all_genes_set = set()
|
| 47 |
for system, gene_list_raw in zip(rxn_df["system"], rxn_df[gene_col]):
|
| 48 |
-
|
| 49 |
-
gene_list = ast.literal_eval(gene_list_raw)
|
| 50 |
-
else:
|
| 51 |
-
gene_list = extract_genes_from_gpa(gene_list_raw)
|
| 52 |
|
| 53 |
if system != "" and system not in system_genes_dict:
|
| 54 |
system_genes_dict[system] = set()
|
|
@@ -64,22 +76,23 @@ def read_system_gene(model_pre_filename):
|
|
| 64 |
missing_gene_system_dict = dict(sorted(missing_gene_system_dict.items()))
|
| 65 |
return system_genes_dict, missing_gene_system_dict, all_genes_set
|
| 66 |
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
# for gene in gene_set:
|
| 72 |
-
# if gene in mapping_dict: # TODO: if not print warning
|
| 73 |
-
# gene_set_new.add(mapping_dict[gene])
|
| 74 |
-
# if gene_set_new:
|
| 75 |
-
# system_genes_dict_new[system] = gene_set_new
|
| 76 |
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
|
|
|
|
| 83 |
|
| 84 |
def filter_geneExpr_df(combined_geneExpr_df, all_genes_set):
|
| 85 |
geneExpr_df = combined_geneExpr_df.loc[combined_geneExpr_df.index.isin(all_genes_set)]
|
|
@@ -148,8 +161,10 @@ def bootstrap_genes(model_pre_filenames, mapping_filenames, species_prefixes, co
|
|
| 148 |
# all_genes_set: set of all the real genes with mapping used in the model of that species
|
| 149 |
system_genes_dict, missing_gene_system_dict, all_genes_set = read_system_gene(model_pre_filename)
|
| 150 |
|
| 151 |
-
#
|
| 152 |
-
|
|
|
|
|
|
|
| 153 |
|
| 154 |
# filter to get only geneExprs for that species
|
| 155 |
geneExpr_df = filter_geneExpr_df(combined_geneExpr_df, all_genes_set)
|
|
|
|
| 16 |
keywords = {'or', 'and', 'not'}
|
| 17 |
return [t for t in tokens if t.lower() not in keywords]
|
| 18 |
|
| 19 |
+
def parse_genes(gene_value):
|
| 20 |
+
"""Parse either a stringified gene list or a boolean gene expression."""
|
| 21 |
+
if pd.isna(gene_value) or str(gene_value).strip() == "":
|
| 22 |
+
return []
|
| 23 |
+
|
| 24 |
+
if isinstance(gene_value, (list, tuple, set)):
|
| 25 |
+
return list(gene_value)
|
| 26 |
+
|
| 27 |
+
try:
|
| 28 |
+
parsed = ast.literal_eval(str(gene_value))
|
| 29 |
+
except (ValueError, SyntaxError):
|
| 30 |
+
return extract_genes_from_gpa(gene_value)
|
| 31 |
+
|
| 32 |
+
if isinstance(parsed, (list, tuple, set)):
|
| 33 |
+
return list(parsed)
|
| 34 |
+
return extract_genes_from_gpa(parsed)
|
| 35 |
+
|
| 36 |
def read_combined_geneExpr(combined_geneExpr_filename):
|
| 37 |
if not os.path.isfile(combined_geneExpr_filename):
|
| 38 |
raise FileNotFoundError(f"Missing combined normalized count file, expected at {combined_geneExpr_filename}")
|
|
|
|
| 45 |
def read_system_gene(model_pre_filename):
|
| 46 |
rxn_df = read_model_excel(model_pre_filename, "Reactions")
|
| 47 |
|
| 48 |
+
# Support both stringified lists and boolean expressions in 'genes'.
|
| 49 |
if "genes" in rxn_df.columns:
|
| 50 |
gene_col = "genes"
|
|
|
|
| 51 |
elif "gpaAssociation" in rxn_df.columns:
|
| 52 |
gene_col = "gpaAssociation"
|
|
|
|
| 53 |
else:
|
| 54 |
raise ValueError(
|
| 55 |
"Reactions sheet must have a 'genes' or 'gpaAssociation' column — "
|
|
|
|
| 60 |
missing_gene_system_dict = {}
|
| 61 |
all_genes_set = set()
|
| 62 |
for system, gene_list_raw in zip(rxn_df["system"], rxn_df[gene_col]):
|
| 63 |
+
gene_list = parse_genes(gene_list_raw)
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
if system != "" and system not in system_genes_dict:
|
| 66 |
system_genes_dict[system] = set()
|
|
|
|
| 76 |
missing_gene_system_dict = dict(sorted(missing_gene_system_dict.items()))
|
| 77 |
return system_genes_dict, missing_gene_system_dict, all_genes_set
|
| 78 |
|
| 79 |
+
def map_genes(mapping_dict, system_genes_dict, missing_gene_system_dict, all_genes_set):
|
| 80 |
+
"""Map model gene tags to expression IDs and retain unmapped tags for bootstrapping."""
|
| 81 |
+
mapped_system_genes = {}
|
| 82 |
+
missing_genes = dict(missing_gene_system_dict)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
+
for system, gene_set in system_genes_dict.items():
|
| 85 |
+
mapped_genes = set()
|
| 86 |
+
for gene in gene_set:
|
| 87 |
+
if gene in mapping_dict:
|
| 88 |
+
mapped_genes.add(mapping_dict[gene])
|
| 89 |
+
else:
|
| 90 |
+
missing_genes.setdefault(gene, system)
|
| 91 |
+
if mapped_genes:
|
| 92 |
+
mapped_system_genes[system] = mapped_genes
|
| 93 |
|
| 94 |
+
mapped_all_genes = {mapping_dict[gene] for gene in all_genes_set if gene in mapping_dict}
|
| 95 |
+
return mapped_system_genes, dict(sorted(missing_genes.items())), mapped_all_genes
|
| 96 |
|
| 97 |
def filter_geneExpr_df(combined_geneExpr_df, all_genes_set):
|
| 98 |
geneExpr_df = combined_geneExpr_df.loc[combined_geneExpr_df.index.isin(all_genes_set)]
|
|
|
|
| 161 |
# all_genes_set: set of all the real genes with mapping used in the model of that species
|
| 162 |
system_genes_dict, missing_gene_system_dict, all_genes_set = read_system_gene(model_pre_filename)
|
| 163 |
|
| 164 |
+
# Map model tags to the annotation IDs used in the expression file.
|
| 165 |
+
system_genes_dict, missing_gene_system_dict, all_genes_set = map_genes(
|
| 166 |
+
mapping_dict, system_genes_dict, missing_gene_system_dict, all_genes_set
|
| 167 |
+
)
|
| 168 |
|
| 169 |
# filter to get only geneExprs for that species
|
| 170 |
geneExpr_df = filter_geneExpr_df(combined_geneExpr_df, all_genes_set)
|