gsrap 0.8.1__py3-none-any.whl → 0.8.2__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.
@@ -5,6 +5,9 @@ import requests
5
5
  import importlib.metadata
6
6
  from datetime import datetime
7
7
  from packaging import version
8
+ import atexit
9
+ import os
10
+
8
11
 
9
12
 
10
13
  import cobra
@@ -69,6 +72,7 @@ def main():
69
72
  parsedb_parser.add_argument("--module", action='store_true', help="Show progress for each module of each map (use only with --progress).")
70
73
  parsedb_parser.add_argument("-f", "--focus", metavar='', type=str, default='-', help="Focus on a particular map/module (use only with --progress).")
71
74
  parsedb_parser.add_argument("-m", "--media", metavar='', type=str, default='M9,M9an,M9photo', help="Media to use during growth simulations (comma-separated IDs).")
75
+ parsedb_parser.add_argument("-z", "--initialize", metavar='', type=str, default='-', help="Initialize the universe on the provided medium. By default, the first medium in --media is used. Use 'none' to avoid initialization.")
72
76
  parsedb_parser.add_argument("--precursors", action='store_true', help="Verify biosynthesis of biomass precursors and show blocked ones.")
73
77
  parsedb_parser.add_argument("--biosynth", action='store_true', help="Check biosynthesis of all metabolites and detect dead-ends.")
74
78
  parsedb_parser.add_argument("-e", "--eggnog", nargs='+', metavar='', type=str, default='-', help="Path to the optional eggnog-mapper annotation table(s).")
@@ -76,6 +80,8 @@ def main():
76
80
  parsedb_parser.add_argument("--goodbefore", metavar='', type=str, default='-', help="Syntax is {pure_mid}-{rid1}-{rid2}. From top to bottom, build the universe until reaction {rid1}, transport {rid2} and metabolite {pure_mid} are reached.")
77
81
  parsedb_parser.add_argument("--onlyauthor", metavar='', type=str, default='-', help="Build the universe by parsing contents of the specified author ID only. Contents affected by --goodbefore are parsed anyway.")
78
82
  parsedb_parser.add_argument("--nofigs", action='store_true', help="Do not generate figures.")
83
+ parsedb_parser.add_argument("-j", "--justparse", action='store_true', help="Just parse the database without performing extra activities (saves time during universe expansion).")
84
+
79
85
 
80
86
 
81
87
  # add arguments for the 'mkmodel' command
@@ -87,10 +93,11 @@ def main():
87
93
  mkmodel_parser.add_argument("-e", "--eggnog", nargs='+', metavar='', type=str, default='-', help="Path to the eggnog-mapper annotation table(s).")
88
94
  mkmodel_parser.add_argument("-k", "--keggorg", metavar='', type=str, default='-', help="A single KEGG Organism code. If provided, it takes precedence over --eggnog.")
89
95
  mkmodel_parser.add_argument("-u", "--universe", metavar='', type=str, default='-', help="Path to the universe model (SBML format).")
90
- mkmodel_parser.add_argument("-i", "--force_inclusion", metavar='', type=str, default='-', help="Force the inclusion of the specified reactions (comma-separated IDs).")
91
- mkmodel_parser.add_argument("-f", "--gap_fill", metavar='', type=str, default='-', help="Media to use during gap-filling (comma-separated IDs); if not provided, gap-filling will be skipped.")
92
- mkmodel_parser.add_argument("-x", "--exclude_orphans", action='store_true', help="Exclude orphan reactions from the gap-filling repository.")
93
- #mkmodel_parser.add_argument("-r", "--force_removal", metavar='', type=str, default='-', help="Force the removal of the specified reactions (comma-separated IDs) (it applies after gap-filling, before Biolog(R)-based curation).")
96
+ mkmodel_parser.add_argument("-i", "--include", metavar='', type=str, default='-', help="Force the inclusion of the specified reactions (comma-separated IDs).")
97
+ mkmodel_parser.add_argument("-f", "--gapfill", metavar='', type=str, default='-', help="Media to use during gap-filling (comma-separated IDs); if not provided, gap-filling will be skipped.")
98
+ mkmodel_parser.add_argument("-z", "--initialize", metavar='', type=str, default='-', help="Initialize the model on the provided medium. By default, the first medium in --gapfill is used. Use 'none' to avoid initialization.")
99
+ mkmodel_parser.add_argument("-x", "--excludeorp", action='store_true', help="Exclude orphan reactions from the gap-filling repository.")
100
+ #mkmodel_parser.add_argument("-r", "--remove", metavar='', type=str, default='-', help="Force the removal of the specified reactions (comma-separated IDs) (it applies after gap-filling, before Biolog(R)-based curation).")
94
101
  mkmodel_parser.add_argument("-l", "--biolog", metavar='', type=str, default='-', help="Strain ID associated to binary Biolog(R) PM1, PM2A, PM3B and PM4A plates; if not provided, Biolog(R)-based model curation will be skipped (use with --cnps and --gap_fill).")
95
102
  mkmodel_parser.add_argument("-s", "--cnps", metavar='', type=str, default='glc__D,nh4,pi,so4', help="Starting C, N, P and S source metabolites (comma-separated IDs).")
96
103
  mkmodel_parser.add_argument("--conditional", metavar='', type=float, default=0.5, help="Expected minimum fraction of reactions in a biosynthetic pathway for an actually present conditional biomass precursor.")
@@ -161,6 +168,15 @@ def main():
161
168
 
162
169
 
163
170
 
171
+ # The following chunk suppresses the warning
172
+ # "sys:1: DeprecationWarning: builtin type swigvarlink has no __module__ attribute"
173
+ # raised at Gsrap shutdown by calling memote.suite.api.test_model() in common/memoteutils.py
174
+ def _suppress_swigvarlink_warning():
175
+ sys.stderr = open(os.devnull, 'w') # tested also with sys.stdout: same effect.
176
+ atexit.register(_suppress_swigvarlink_warning)
177
+
178
+
179
+
164
180
  # run the program:
165
181
  set_usual_formatter(logger.handlers[0])
166
182
  current_date_time = datetime.now()
gsrap/__init__.py CHANGED
@@ -5,6 +5,9 @@ import requests
5
5
  import importlib.metadata
6
6
  from datetime import datetime
7
7
  from packaging import version
8
+ import atexit
9
+ import os
10
+
8
11
 
9
12
 
10
13
  import cobra
@@ -69,6 +72,7 @@ def main():
69
72
  parsedb_parser.add_argument("--module", action='store_true', help="Show progress for each module of each map (use only with --progress).")
70
73
  parsedb_parser.add_argument("-f", "--focus", metavar='', type=str, default='-', help="Focus on a particular map/module (use only with --progress).")
71
74
  parsedb_parser.add_argument("-m", "--media", metavar='', type=str, default='M9,M9an,M9photo', help="Media to use during growth simulations (comma-separated IDs).")
75
+ parsedb_parser.add_argument("-z", "--initialize", metavar='', type=str, default='-', help="Initialize the universe on the provided medium. By default, the first medium in --media is used. Use 'none' to avoid initialization.")
72
76
  parsedb_parser.add_argument("--precursors", action='store_true', help="Verify biosynthesis of biomass precursors and show blocked ones.")
73
77
  parsedb_parser.add_argument("--biosynth", action='store_true', help="Check biosynthesis of all metabolites and detect dead-ends.")
74
78
  parsedb_parser.add_argument("-e", "--eggnog", nargs='+', metavar='', type=str, default='-', help="Path to the optional eggnog-mapper annotation table(s).")
@@ -76,6 +80,8 @@ def main():
76
80
  parsedb_parser.add_argument("--goodbefore", metavar='', type=str, default='-', help="Syntax is {pure_mid}-{rid1}-{rid2}. From top to bottom, build the universe until reaction {rid1}, transport {rid2} and metabolite {pure_mid} are reached.")
77
81
  parsedb_parser.add_argument("--onlyauthor", metavar='', type=str, default='-', help="Build the universe by parsing contents of the specified author ID only. Contents affected by --goodbefore are parsed anyway.")
78
82
  parsedb_parser.add_argument("--nofigs", action='store_true', help="Do not generate figures.")
83
+ parsedb_parser.add_argument("-j", "--justparse", action='store_true', help="Just parse the database without performing extra activities (saves time during universe expansion).")
84
+
79
85
 
80
86
 
81
87
  # add arguments for the 'mkmodel' command
@@ -87,10 +93,11 @@ def main():
87
93
  mkmodel_parser.add_argument("-e", "--eggnog", nargs='+', metavar='', type=str, default='-', help="Path to the eggnog-mapper annotation table(s).")
88
94
  mkmodel_parser.add_argument("-k", "--keggorg", metavar='', type=str, default='-', help="A single KEGG Organism code. If provided, it takes precedence over --eggnog.")
89
95
  mkmodel_parser.add_argument("-u", "--universe", metavar='', type=str, default='-', help="Path to the universe model (SBML format).")
90
- mkmodel_parser.add_argument("-i", "--force_inclusion", metavar='', type=str, default='-', help="Force the inclusion of the specified reactions (comma-separated IDs).")
91
- mkmodel_parser.add_argument("-f", "--gap_fill", metavar='', type=str, default='-', help="Media to use during gap-filling (comma-separated IDs); if not provided, gap-filling will be skipped.")
92
- mkmodel_parser.add_argument("-x", "--exclude_orphans", action='store_true', help="Exclude orphan reactions from the gap-filling repository.")
93
- #mkmodel_parser.add_argument("-r", "--force_removal", metavar='', type=str, default='-', help="Force the removal of the specified reactions (comma-separated IDs) (it applies after gap-filling, before Biolog(R)-based curation).")
96
+ mkmodel_parser.add_argument("-i", "--include", metavar='', type=str, default='-', help="Force the inclusion of the specified reactions (comma-separated IDs).")
97
+ mkmodel_parser.add_argument("-f", "--gapfill", metavar='', type=str, default='-', help="Media to use during gap-filling (comma-separated IDs); if not provided, gap-filling will be skipped.")
98
+ mkmodel_parser.add_argument("-z", "--initialize", metavar='', type=str, default='-', help="Initialize the model on the provided medium. By default, the first medium in --gapfill is used. Use 'none' to avoid initialization.")
99
+ mkmodel_parser.add_argument("-x", "--excludeorp", action='store_true', help="Exclude orphan reactions from the gap-filling repository.")
100
+ #mkmodel_parser.add_argument("-r", "--remove", metavar='', type=str, default='-', help="Force the removal of the specified reactions (comma-separated IDs) (it applies after gap-filling, before Biolog(R)-based curation).")
94
101
  mkmodel_parser.add_argument("-l", "--biolog", metavar='', type=str, default='-', help="Strain ID associated to binary Biolog(R) PM1, PM2A, PM3B and PM4A plates; if not provided, Biolog(R)-based model curation will be skipped (use with --cnps and --gap_fill).")
95
102
  mkmodel_parser.add_argument("-s", "--cnps", metavar='', type=str, default='glc__D,nh4,pi,so4', help="Starting C, N, P and S source metabolites (comma-separated IDs).")
96
103
  mkmodel_parser.add_argument("--conditional", metavar='', type=float, default=0.5, help="Expected minimum fraction of reactions in a biosynthetic pathway for an actually present conditional biomass precursor.")
@@ -161,6 +168,15 @@ def main():
161
168
 
162
169
 
163
170
 
171
+ # The following chunk suppresses the warning
172
+ # "sys:1: DeprecationWarning: builtin type swigvarlink has no __module__ attribute"
173
+ # raised at Gsrap shutdown by calling memote.suite.api.test_model() in common/memoteutils.py
174
+ def _suppress_swigvarlink_warning():
175
+ sys.stderr = open(os.devnull, 'w') # tested also with sys.stdout: same effect.
176
+ atexit.register(_suppress_swigvarlink_warning)
177
+
178
+
179
+
164
180
  # run the program:
165
181
  set_usual_formatter(logger.handlers[0])
166
182
  current_date_time = datetime.now()
@@ -8,3 +8,4 @@ from .sbmlutils import *
8
8
  from .escherutils import *
9
9
  from .logutils import *
10
10
  from .keggutils import *
11
+ from .memoteutils import *
@@ -1,3 +1,6 @@
1
+ import importlib.metadata
2
+
3
+
1
4
  import pandas as pnd
2
5
 
3
6
 
@@ -5,7 +8,51 @@ from .figures import figure_df_C_F1
5
8
 
6
9
 
7
10
 
8
- def write_excel_model(model, filepath, nofigs, df_E, df_B, df_P, df_S, df_C=None):
11
+
12
+ def get_summary_sheet(model, memote_results_dict):
13
+ df_gsrap = [
14
+ # Gsrap
15
+ {'c1': 'Gsrap version', 'c2': f"v{importlib.metadata.metadata('gsrap')['Version']}", 'c3': '', 'c4': ''},
16
+ {'c1': 'Model ID', 'c2': f"{model.id}", 'c3': '', 'c4': ''},
17
+ {'c1': 'Compartments', 'c2': f"{len(model.compartments)}", 'c3': '', 'c4': ''},
18
+ {'c1': 'Metabolites', 'c2': f"{len(model.metabolites)}", 'c3': '', 'c4': ''},
19
+ {'c1': '', 'c2': 'Unique', 'c3': f"{len(set([m.id.rsplit('_',1)[0] for m in model.metabolites]))}", 'c4': ''},
20
+ {'c1': 'Reactions', 'c2': f"{len(model.reactions)}", 'c3': '', 'c4': ''},
21
+ {'c1': '', 'c2': 'Non-transport', 'c3': f"{len([r for r in model.reactions if ((r.id != 'Biomass' and len(r.metabolites)!=1) and len(set([m.id.rsplit('_',1)[-1] for m in r.metabolites]))==1)])}", 'c4': ''},
22
+ {'c1': '', 'c2': 'Transport', 'c3': f"{len([r for r in model.reactions if ((r.id != 'Biomass' and len(r.metabolites)!=1) and len(set([m.id.rsplit('_',1)[-1] for m in r.metabolites]))>1)])}", 'c4': ''},
23
+ {'c1': '', 'c2': 'Artificial', 'c3': f"{len([r for r in model.reactions if ((r.id == 'Biomass' or len(r.metabolites)==1))])}", 'c4': ''},
24
+ {'c1': 'Genes', 'c2': f"{len(model.genes)}", 'c3': '', 'c4': ''},
25
+ # empty line
26
+ {'c1': '', 'c2': '', 'c3': '', 'c4': ''},
27
+ ]
28
+ df_gsrap = pnd.DataFrame.from_records(df_gsrap)
29
+ if memote_results_dict != None:
30
+ df_memote = [
31
+ # MEMOTE
32
+ {'c1': 'MEMOTE version', 'c2': f"v{memote_results_dict['version']}", 'c3': '', 'c4': ''},
33
+ {'c1': 'MEMOTE Total Score', 'c2': f"{memote_results_dict['total']}%", 'c3': '', 'c4': ''},
34
+ {'c1': 'MEMOTE consistency', 'c2': f"{memote_results_dict['consistency']['sub_total']}%", 'c3': '', 'c4': ''},
35
+ {'c1': '', 'c2': 'stoichiometric consistency', 'c3': f"{memote_results_dict['consistency']['test_stoichiometric_consistency']}%", 'c4': ''},
36
+ {'c1': '', 'c2': 'mass balance', 'c3': f"{memote_results_dict['consistency']['test_reaction_mass_balance']}%", 'c4': ''},
37
+ {'c1': '', 'c2': 'charge balance', 'c3': f"{memote_results_dict['consistency']['test_reaction_charge_balance']}%", 'c4': ''},
38
+ {'c1': '', 'c2': 'disconnected metabolites', 'c3': f"{memote_results_dict['consistency']['test_reaction_charge_balance']}%", 'c4': ''},
39
+ {'c1': '', 'c2': 'unbounded flux in default conditions', 'c3': f"{memote_results_dict['consistency']['test_find_reactions_unbounded_flux_default_condition']}%", 'c4': ''},
40
+ {'c1': 'MEMOTE annotation Metabolites', 'c2': f"{memote_results_dict['annotation_M']['sub_total']}%", 'c3': '', 'c4': ''},
41
+ {'c1': 'MEMOTE annotation Reactions', 'c2': f"{memote_results_dict['annotation_R']['sub_total']}%", 'c3': '', 'c4': ''},
42
+ {'c1': 'MEMOTE annotation Genes', 'c2': f"{memote_results_dict['annotation_G']['sub_total']}%", 'c3': '', 'c4': ''},
43
+ {'c1': 'MEMOTE annotation SBO', 'c2': f"{memote_results_dict['annotation_SBO']['sub_total']}%", 'c3': '', 'c4': ''},
44
+ ]
45
+ df_memote = pnd.DataFrame.from_records(df_memote)
46
+ else:
47
+ df_memote = pnd.DataFrame()
48
+
49
+
50
+ df = pnd.concat([df_gsrap, df_memote])
51
+ return df
52
+
53
+
54
+
55
+ def write_excel_model(model, filepath, nofigs, memote_results_dict, df_E, df_B, df_P, df_S, df_C=None):
9
56
 
10
57
 
11
58
  # generate figures
@@ -130,6 +177,7 @@ def write_excel_model(model, filepath, nofigs, df_E, df_B, df_P, df_S, df_C=None
130
177
 
131
178
 
132
179
  with pnd.ExcelWriter(filepath, engine='xlsxwriter') as writer:
180
+ get_summary_sheet(model, memote_results_dict).to_excel(writer, sheet_name='Summary', index=False, header=False)
133
181
  df_M.to_excel(writer, sheet_name='Metabolites', index=False)
134
182
  df_R.to_excel(writer, sheet_name='Reactions', index=False)
135
183
  df_T.to_excel(writer, sheet_name='Transporters', index=False)
@@ -1,6 +1,10 @@
1
1
  import gempipe
2
2
 
3
3
 
4
+ from .fluxbal import fba_no_warnings
5
+
6
+
7
+
4
8
 
5
9
  def apply_medium_given_column(logger, model, medium, column, is_reference=False):
6
10
 
@@ -80,4 +84,36 @@ def apply_medium_given_column(logger, model, medium, column, is_reference=False)
80
84
  model.reactions.get_by_id(f'EX_{substrate}_e').lower_bound = value -error
81
85
  model.reactions.get_by_id(f'EX_{substrate}_e').upper_bound = value +error
82
86
 
87
+ return 0
88
+
89
+
90
+
91
+ def initialize_model(logger, model, dbexp, initialize, media):
92
+
93
+
94
+ if initialize in ['None', 'none']:
95
+ logger.info(f"Initialization will be skipped.")
96
+ return 0
97
+ elif initialize == '-':
98
+ if media == '-':
99
+ logger.info(f"No media provided: initialization will be skipped.")
100
+ return 0
101
+ else:
102
+ media = media.split(',')
103
+ medium = media[0] # taking the first medium
104
+ else:
105
+ medium = initialize
106
+
107
+
108
+ if medium not in dbexp['media'].columns:
109
+ logger.warning(f"Medium '{medium}' does not exists: initialization will be skipped.")
110
+ return 0
111
+
112
+
113
+ response = apply_medium_given_column(logger, model, medium, dbexp['media'][medium])
114
+ if response == 1: return 1
115
+ res, obj_value, status = fba_no_warnings(model)
116
+ logger.info(f"Initialized on medium '{medium}': {obj_value} ({status})")
117
+
118
+
83
119
  return 0
@@ -0,0 +1,132 @@
1
+ import os
2
+ import contextlib
3
+ import importlib.metadata
4
+
5
+
6
+
7
+ import memote
8
+
9
+
10
+
11
+
12
+ def get_memote_results_dict(logger, model):
13
+
14
+
15
+ logger.info(f"Running selected modules of MEMOTE v{importlib.metadata.metadata('memote')['Version']}...")
16
+
17
+
18
+ # launch memote (only relevant modules)
19
+ with open(os.devnull, 'w') as devnull:
20
+ with contextlib.redirect_stdout(devnull), contextlib.redirect_stderr(devnull):
21
+ try: memote_report = memote.suite.api.test_model(model, exclusive=[
22
+ 'test_annotation',
23
+ 'test_sbo',
24
+ 'test_stoichiometric_consistency',
25
+ 'test_reaction_mass_balance',
26
+ 'test_reaction_charge_balance',
27
+ 'test_find_disconnected',
28
+ 'test_find_reactions_unbounded_flux_default_condition'], results=True)
29
+ except ValueError: memote_report = None
30
+
31
+
32
+ # parse memote's results
33
+ results_dict = {}
34
+ results_dict['version'] = importlib.metadata.version("memote")
35
+ test_results = dict(memote_report[1])['tests']
36
+ sections = {
37
+ 'consistency': [
38
+ ('test_stoichiometric_consistency', 3),
39
+ ('test_reaction_mass_balance', 1),
40
+ ('test_reaction_charge_balance', 1),
41
+ ('test_find_disconnected', 1),
42
+ ('test_find_reactions_unbounded_flux_default_condition', 1)
43
+ ],
44
+ 'annotation_M': [
45
+ ('test_metabolite_annotation_presence', 1),
46
+ ('test_metabolite_annotation_overview', 1),
47
+ ('test_metabolite_annotation_wrong_ids', 1),
48
+ ('test_metabolite_id_namespace_consistency', 1),
49
+ ],
50
+ 'annotation_R': [
51
+ ('test_reaction_annotation_presence', 1),
52
+ ('test_reaction_annotation_overview', 1),
53
+ ('test_reaction_annotation_wrong_ids', 1),
54
+ ('test_reaction_id_namespace_consistency', 1),
55
+ ],
56
+ 'annotation_G': [
57
+ ('test_gene_product_annotation_presence', 1),
58
+ ('test_gene_product_annotation_overview', 1),
59
+ ('test_gene_product_annotation_wrong_ids', 1),
60
+ ],
61
+ 'annotation_SBO': [
62
+ ('test_metabolite_sbo_presence', 1),
63
+ ('test_metabolite_specific_sbo_presence', 1),
64
+ ('test_reaction_sbo_presence', 1),
65
+ ('test_metabolic_reaction_specific_sbo_presence', 1),
66
+ ('test_transport_reaction_specific_sbo_presence', 1),
67
+ ('test_exchange_specific_sbo_presence', 1),
68
+ ('test_demand_specific_sbo_presence', 1),
69
+ ('test_sink_specific_sbo_presence', 1),
70
+ ('test_gene_sbo_presence', 1),
71
+ ('test_gene_specific_sbo_presence', 1),
72
+ ('test_biomass_specific_sbo_presence', 1),
73
+ ],
74
+ }
75
+ section_multipliers = {
76
+ 'consistency': 3,
77
+ 'annotation_M': 1,
78
+ 'annotation_R': 1,
79
+ 'annotation_G': 1,
80
+ 'annotation_SBO': 2,
81
+ }
82
+
83
+
84
+ numerator_total = 0
85
+ denominator_total = 0
86
+ for section, metrics in sections.items():
87
+ numerator = 0
88
+ denominator = 0
89
+ results_dict[section] = {}
90
+
91
+
92
+ # iterate metrics of this section:
93
+ for metric, metric_multiplier in metrics:
94
+ metric_raw = test_results[metric]['metric']
95
+
96
+
97
+ # no subcategories here:
98
+ if type(metric_raw) == float:
99
+ metric_percentage = ((1- metric_raw ) *100)
100
+ numerator = numerator + (metric_percentage * metric_multiplier)
101
+ denominator = denominator + metric_multiplier
102
+ results_dict[section][metric] = round(metric_percentage, 1)
103
+
104
+
105
+ # there are subcategories (like in the case of M/R/G/SBO annots)
106
+ else:
107
+ results_dict[section][metric] = {}
108
+ for key, value in metric_raw.items():
109
+ n_subcategories = len(metric_raw)
110
+ multiplier_corrected = metric_multiplier / n_subcategories
111
+ metric_percentage = ((1- value ) *100)
112
+ numerator = numerator + (metric_percentage * multiplier_corrected)
113
+ denominator = denominator + multiplier_corrected
114
+ results_dict[section][metric][key] = round(metric_percentage, 1)
115
+
116
+
117
+ # compute the subtotal:
118
+ sub_total = numerator / denominator
119
+ results_dict[section]['sub_total'] = int(round(sub_total, 0))
120
+
121
+
122
+ # compute the total:
123
+ denominator_total = denominator_total + section_multipliers[section] *denominator
124
+ numerator_total = numerator_total + section_multipliers[section] *numerator
125
+ total = numerator_total / denominator_total
126
+ results_dict['total'] = int(round(total, 0))
127
+
128
+
129
+ logger.info(f"Done! MEMOTE Total Score: {results_dict['total']}%.")
130
+
131
+
132
+ return results_dict
gsrap/commons/__init__.py CHANGED
@@ -8,3 +8,4 @@ from .sbmlutils import *
8
8
  from .escherutils import *
9
9
  from .logutils import *
10
10
  from .keggutils import *
11
+ from .memoteutils import *
gsrap/commons/excelhub.py CHANGED
@@ -1,3 +1,6 @@
1
+ import importlib.metadata
2
+
3
+
1
4
  import pandas as pnd
2
5
 
3
6
 
@@ -5,7 +8,51 @@ from .figures import figure_df_C_F1
5
8
 
6
9
 
7
10
 
8
- def write_excel_model(model, filepath, nofigs, df_E, df_B, df_P, df_S, df_C=None):
11
+
12
+ def get_summary_sheet(model, memote_results_dict):
13
+ df_gsrap = [
14
+ # Gsrap
15
+ {'c1': 'Gsrap version', 'c2': f"v{importlib.metadata.metadata('gsrap')['Version']}", 'c3': '', 'c4': ''},
16
+ {'c1': 'Model ID', 'c2': f"{model.id}", 'c3': '', 'c4': ''},
17
+ {'c1': 'Compartments', 'c2': f"{len(model.compartments)}", 'c3': '', 'c4': ''},
18
+ {'c1': 'Metabolites', 'c2': f"{len(model.metabolites)}", 'c3': '', 'c4': ''},
19
+ {'c1': '', 'c2': 'Unique', 'c3': f"{len(set([m.id.rsplit('_',1)[0] for m in model.metabolites]))}", 'c4': ''},
20
+ {'c1': 'Reactions', 'c2': f"{len(model.reactions)}", 'c3': '', 'c4': ''},
21
+ {'c1': '', 'c2': 'Non-transport', 'c3': f"{len([r for r in model.reactions if ((r.id != 'Biomass' and len(r.metabolites)!=1) and len(set([m.id.rsplit('_',1)[-1] for m in r.metabolites]))==1)])}", 'c4': ''},
22
+ {'c1': '', 'c2': 'Transport', 'c3': f"{len([r for r in model.reactions if ((r.id != 'Biomass' and len(r.metabolites)!=1) and len(set([m.id.rsplit('_',1)[-1] for m in r.metabolites]))>1)])}", 'c4': ''},
23
+ {'c1': '', 'c2': 'Artificial', 'c3': f"{len([r for r in model.reactions if ((r.id == 'Biomass' or len(r.metabolites)==1))])}", 'c4': ''},
24
+ {'c1': 'Genes', 'c2': f"{len(model.genes)}", 'c3': '', 'c4': ''},
25
+ # empty line
26
+ {'c1': '', 'c2': '', 'c3': '', 'c4': ''},
27
+ ]
28
+ df_gsrap = pnd.DataFrame.from_records(df_gsrap)
29
+ if memote_results_dict != None:
30
+ df_memote = [
31
+ # MEMOTE
32
+ {'c1': 'MEMOTE version', 'c2': f"v{memote_results_dict['version']}", 'c3': '', 'c4': ''},
33
+ {'c1': 'MEMOTE Total Score', 'c2': f"{memote_results_dict['total']}%", 'c3': '', 'c4': ''},
34
+ {'c1': 'MEMOTE consistency', 'c2': f"{memote_results_dict['consistency']['sub_total']}%", 'c3': '', 'c4': ''},
35
+ {'c1': '', 'c2': 'stoichiometric consistency', 'c3': f"{memote_results_dict['consistency']['test_stoichiometric_consistency']}%", 'c4': ''},
36
+ {'c1': '', 'c2': 'mass balance', 'c3': f"{memote_results_dict['consistency']['test_reaction_mass_balance']}%", 'c4': ''},
37
+ {'c1': '', 'c2': 'charge balance', 'c3': f"{memote_results_dict['consistency']['test_reaction_charge_balance']}%", 'c4': ''},
38
+ {'c1': '', 'c2': 'disconnected metabolites', 'c3': f"{memote_results_dict['consistency']['test_reaction_charge_balance']}%", 'c4': ''},
39
+ {'c1': '', 'c2': 'unbounded flux in default conditions', 'c3': f"{memote_results_dict['consistency']['test_find_reactions_unbounded_flux_default_condition']}%", 'c4': ''},
40
+ {'c1': 'MEMOTE annotation Metabolites', 'c2': f"{memote_results_dict['annotation_M']['sub_total']}%", 'c3': '', 'c4': ''},
41
+ {'c1': 'MEMOTE annotation Reactions', 'c2': f"{memote_results_dict['annotation_R']['sub_total']}%", 'c3': '', 'c4': ''},
42
+ {'c1': 'MEMOTE annotation Genes', 'c2': f"{memote_results_dict['annotation_G']['sub_total']}%", 'c3': '', 'c4': ''},
43
+ {'c1': 'MEMOTE annotation SBO', 'c2': f"{memote_results_dict['annotation_SBO']['sub_total']}%", 'c3': '', 'c4': ''},
44
+ ]
45
+ df_memote = pnd.DataFrame.from_records(df_memote)
46
+ else:
47
+ df_memote = pnd.DataFrame()
48
+
49
+
50
+ df = pnd.concat([df_gsrap, df_memote])
51
+ return df
52
+
53
+
54
+
55
+ def write_excel_model(model, filepath, nofigs, memote_results_dict, df_E, df_B, df_P, df_S, df_C=None):
9
56
 
10
57
 
11
58
  # generate figures
@@ -130,6 +177,7 @@ def write_excel_model(model, filepath, nofigs, df_E, df_B, df_P, df_S, df_C=None
130
177
 
131
178
 
132
179
  with pnd.ExcelWriter(filepath, engine='xlsxwriter') as writer:
180
+ get_summary_sheet(model, memote_results_dict).to_excel(writer, sheet_name='Summary', index=False, header=False)
133
181
  df_M.to_excel(writer, sheet_name='Metabolites', index=False)
134
182
  df_R.to_excel(writer, sheet_name='Reactions', index=False)
135
183
  df_T.to_excel(writer, sheet_name='Transporters', index=False)
gsrap/commons/medium.py CHANGED
@@ -1,6 +1,10 @@
1
1
  import gempipe
2
2
 
3
3
 
4
+ from .fluxbal import fba_no_warnings
5
+
6
+
7
+
4
8
 
5
9
  def apply_medium_given_column(logger, model, medium, column, is_reference=False):
6
10
 
@@ -80,4 +84,36 @@ def apply_medium_given_column(logger, model, medium, column, is_reference=False)
80
84
  model.reactions.get_by_id(f'EX_{substrate}_e').lower_bound = value -error
81
85
  model.reactions.get_by_id(f'EX_{substrate}_e').upper_bound = value +error
82
86
 
87
+ return 0
88
+
89
+
90
+
91
+ def initialize_model(logger, model, dbexp, initialize, media):
92
+
93
+
94
+ if initialize in ['None', 'none']:
95
+ logger.info(f"Initialization will be skipped.")
96
+ return 0
97
+ elif initialize == '-':
98
+ if media == '-':
99
+ logger.info(f"No media provided: initialization will be skipped.")
100
+ return 0
101
+ else:
102
+ media = media.split(',')
103
+ medium = media[0] # taking the first medium
104
+ else:
105
+ medium = initialize
106
+
107
+
108
+ if medium not in dbexp['media'].columns:
109
+ logger.warning(f"Medium '{medium}' does not exists: initialization will be skipped.")
110
+ return 0
111
+
112
+
113
+ response = apply_medium_given_column(logger, model, medium, dbexp['media'][medium])
114
+ if response == 1: return 1
115
+ res, obj_value, status = fba_no_warnings(model)
116
+ logger.info(f"Initialized on medium '{medium}': {obj_value} ({status})")
117
+
118
+
83
119
  return 0
@@ -0,0 +1,132 @@
1
+ import os
2
+ import contextlib
3
+ import importlib.metadata
4
+
5
+
6
+
7
+ import memote
8
+
9
+
10
+
11
+
12
+ def get_memote_results_dict(logger, model):
13
+
14
+
15
+ logger.info(f"Running selected modules of MEMOTE v{importlib.metadata.metadata('memote')['Version']}...")
16
+
17
+
18
+ # launch memote (only relevant modules)
19
+ with open(os.devnull, 'w') as devnull:
20
+ with contextlib.redirect_stdout(devnull), contextlib.redirect_stderr(devnull):
21
+ try: memote_report = memote.suite.api.test_model(model, exclusive=[
22
+ 'test_annotation',
23
+ 'test_sbo',
24
+ 'test_stoichiometric_consistency',
25
+ 'test_reaction_mass_balance',
26
+ 'test_reaction_charge_balance',
27
+ 'test_find_disconnected',
28
+ 'test_find_reactions_unbounded_flux_default_condition'], results=True)
29
+ except ValueError: memote_report = None
30
+
31
+
32
+ # parse memote's results
33
+ results_dict = {}
34
+ results_dict['version'] = importlib.metadata.version("memote")
35
+ test_results = dict(memote_report[1])['tests']
36
+ sections = {
37
+ 'consistency': [
38
+ ('test_stoichiometric_consistency', 3),
39
+ ('test_reaction_mass_balance', 1),
40
+ ('test_reaction_charge_balance', 1),
41
+ ('test_find_disconnected', 1),
42
+ ('test_find_reactions_unbounded_flux_default_condition', 1)
43
+ ],
44
+ 'annotation_M': [
45
+ ('test_metabolite_annotation_presence', 1),
46
+ ('test_metabolite_annotation_overview', 1),
47
+ ('test_metabolite_annotation_wrong_ids', 1),
48
+ ('test_metabolite_id_namespace_consistency', 1),
49
+ ],
50
+ 'annotation_R': [
51
+ ('test_reaction_annotation_presence', 1),
52
+ ('test_reaction_annotation_overview', 1),
53
+ ('test_reaction_annotation_wrong_ids', 1),
54
+ ('test_reaction_id_namespace_consistency', 1),
55
+ ],
56
+ 'annotation_G': [
57
+ ('test_gene_product_annotation_presence', 1),
58
+ ('test_gene_product_annotation_overview', 1),
59
+ ('test_gene_product_annotation_wrong_ids', 1),
60
+ ],
61
+ 'annotation_SBO': [
62
+ ('test_metabolite_sbo_presence', 1),
63
+ ('test_metabolite_specific_sbo_presence', 1),
64
+ ('test_reaction_sbo_presence', 1),
65
+ ('test_metabolic_reaction_specific_sbo_presence', 1),
66
+ ('test_transport_reaction_specific_sbo_presence', 1),
67
+ ('test_exchange_specific_sbo_presence', 1),
68
+ ('test_demand_specific_sbo_presence', 1),
69
+ ('test_sink_specific_sbo_presence', 1),
70
+ ('test_gene_sbo_presence', 1),
71
+ ('test_gene_specific_sbo_presence', 1),
72
+ ('test_biomass_specific_sbo_presence', 1),
73
+ ],
74
+ }
75
+ section_multipliers = {
76
+ 'consistency': 3,
77
+ 'annotation_M': 1,
78
+ 'annotation_R': 1,
79
+ 'annotation_G': 1,
80
+ 'annotation_SBO': 2,
81
+ }
82
+
83
+
84
+ numerator_total = 0
85
+ denominator_total = 0
86
+ for section, metrics in sections.items():
87
+ numerator = 0
88
+ denominator = 0
89
+ results_dict[section] = {}
90
+
91
+
92
+ # iterate metrics of this section:
93
+ for metric, metric_multiplier in metrics:
94
+ metric_raw = test_results[metric]['metric']
95
+
96
+
97
+ # no subcategories here:
98
+ if type(metric_raw) == float:
99
+ metric_percentage = ((1- metric_raw ) *100)
100
+ numerator = numerator + (metric_percentage * metric_multiplier)
101
+ denominator = denominator + metric_multiplier
102
+ results_dict[section][metric] = round(metric_percentage, 1)
103
+
104
+
105
+ # there are subcategories (like in the case of M/R/G/SBO annots)
106
+ else:
107
+ results_dict[section][metric] = {}
108
+ for key, value in metric_raw.items():
109
+ n_subcategories = len(metric_raw)
110
+ multiplier_corrected = metric_multiplier / n_subcategories
111
+ metric_percentage = ((1- value ) *100)
112
+ numerator = numerator + (metric_percentage * multiplier_corrected)
113
+ denominator = denominator + multiplier_corrected
114
+ results_dict[section][metric][key] = round(metric_percentage, 1)
115
+
116
+
117
+ # compute the subtotal:
118
+ sub_total = numerator / denominator
119
+ results_dict[section]['sub_total'] = int(round(sub_total, 0))
120
+
121
+
122
+ # compute the total:
123
+ denominator_total = denominator_total + section_multipliers[section] *denominator
124
+ numerator_total = numerator_total + section_multipliers[section] *numerator
125
+ total = numerator_total / denominator_total
126
+ results_dict['total'] = int(round(total, 0))
127
+
128
+
129
+ logger.info(f"Done! MEMOTE Total Score: {results_dict['total']}%.")
130
+
131
+
132
+ return results_dict
@@ -41,8 +41,12 @@ from ..commons import log_unbalances
41
41
  from ..commons import format_expansion
42
42
  from ..commons import comparative_table
43
43
  from ..commons import download_keggorg
44
+ from ..commons import initialize_model
45
+ from ..commons import get_memote_results_dict
46
+
44
47
 
45
48
  from ..runsims.biosynth import biosynthesis_on_media
49
+ from ..runsims.simplegrowth import grow_on_media
46
50
 
47
51
  from ..parsedb.cycles import verify_egc_all
48
52
 
@@ -103,7 +107,7 @@ def create_model_incore(params):
103
107
 
104
108
  ###### GAPFILLING
105
109
  # force inclusion of reactions:
106
- include_forced(logger, model, universe, args.force_inclusion)
110
+ include_forced(logger, model, universe, args.include)
107
111
 
108
112
  # remove missing conditional precursors + get the 'cond_col_dict' dict.
109
113
  # 'cond_col_dict' is str-to-str: {'pheme_c': 'M00868: 1/8; M00121: 2/12;', 'hemeO_c': 'gr_HemeO: 0/1'}
@@ -114,15 +118,15 @@ def create_model_incore(params):
114
118
  if response == 1: return 1
115
119
 
116
120
  # gap-fill based on media:
117
- df_B = gapfill_on_media(logger, model, universe, dbexp, args.gap_fill, cond_col_dict, args.exclude_orphans)
121
+ df_B = gapfill_on_media(logger, model, universe, dbexp, args.gapfill, cond_col_dict, args.excludeorp)
118
122
  if type(df_B)==int: return 1
119
123
 
120
124
  # force removal of reactions
121
- setattr(args, 'force_removal', '-') # experimental feature, not public. It's main purpose was to test gap-filling in biolog_on_media().
122
- remove_forced(logger, model, universe, args.force_removal)
125
+ setattr(args, 'remove', '-') # experimental feature, not public. It's main purpose was to test gap-filling in biolog_on_media().
126
+ remove_forced(logger, model, universe, args.remove)
123
127
 
124
128
  # perform Biolog(R) curation based on media
125
- df_P = biolog_on_media(logger, model, universe, dbexp, args.gap_fill, args.biolog, args.exclude_orphans, args.cnps)
129
+ df_P = biolog_on_media(logger, model, universe, dbexp, args.gapfill, args.biolog, args.excludeorp, args.cnps)
126
130
  if type(df_P)==int: return 1
127
131
 
128
132
 
@@ -142,12 +146,12 @@ def create_model_incore(params):
142
146
 
143
147
 
144
148
 
145
- ###### CHECKS
149
+ ###### CHECKS 1
146
150
  # check erroneous EGCs
147
151
  verify_egc_all(logger, model, args.outdir)
148
152
 
149
153
  # check blocked metabolites / dead-ends
150
- df_S = biosynthesis_on_media(logger, model, dbexp, args.gap_fill, args.biosynth)
154
+ df_S = biosynthesis_on_media(logger, model, dbexp, args.gapfill, args.biosynth)
151
155
  if type(df_S)==int: return 1
152
156
 
153
157
 
@@ -155,6 +159,16 @@ def create_model_incore(params):
155
159
  ###### POLISHING 3
156
160
  # reset growth environment befor saving the model
157
161
  gempipe.reset_growth_env(model)
162
+
163
+ # initialize model
164
+ response = initialize_model(logger, model, dbexp, args.initialize, args.gapfill)
165
+ if response==1: return 1
166
+
167
+
168
+
169
+ ###### CHECKS 2
170
+ # compute Memote metrics
171
+ memote_results_dict = get_memote_results_dict(logger, model)
158
172
 
159
173
 
160
174
 
@@ -165,7 +179,7 @@ def create_model_incore(params):
165
179
  cobra.io.write_sbml_model(model, f'{args.outdir}/{model.id}.xml') # SBML # groups are saved only to SBML
166
180
  logger.info(f"'{args.outdir}/{model.id}.xml' created!")
167
181
  force_id_on_sbml(f'{args.outdir}/{model.id}.xml', model.id) # force introduction of the 'id=""' field
168
- sheets_dict = write_excel_model(model, f'{args.outdir}/{model.id}.mkmodel.xlsx', args.nofigs, None, df_B, df_P, df_S)
182
+ sheets_dict = write_excel_model(model, f'{args.outdir}/{model.id}.mkmodel.xlsx', args.nofigs, memote_results_dict, None, df_B, df_P, df_S)
169
183
  logger.info(f"'{args.outdir}/{model.id}.mkmodel.xlsx' created!")
170
184
 
171
185
 
gsrap/mkmodel/mkmodel.py CHANGED
@@ -41,8 +41,12 @@ from ..commons import log_unbalances
41
41
  from ..commons import format_expansion
42
42
  from ..commons import comparative_table
43
43
  from ..commons import download_keggorg
44
+ from ..commons import initialize_model
45
+ from ..commons import get_memote_results_dict
46
+
44
47
 
45
48
  from ..runsims.biosynth import biosynthesis_on_media
49
+ from ..runsims.simplegrowth import grow_on_media
46
50
 
47
51
  from ..parsedb.cycles import verify_egc_all
48
52
 
@@ -103,7 +107,7 @@ def create_model_incore(params):
103
107
 
104
108
  ###### GAPFILLING
105
109
  # force inclusion of reactions:
106
- include_forced(logger, model, universe, args.force_inclusion)
110
+ include_forced(logger, model, universe, args.include)
107
111
 
108
112
  # remove missing conditional precursors + get the 'cond_col_dict' dict.
109
113
  # 'cond_col_dict' is str-to-str: {'pheme_c': 'M00868: 1/8; M00121: 2/12;', 'hemeO_c': 'gr_HemeO: 0/1'}
@@ -114,15 +118,15 @@ def create_model_incore(params):
114
118
  if response == 1: return 1
115
119
 
116
120
  # gap-fill based on media:
117
- df_B = gapfill_on_media(logger, model, universe, dbexp, args.gap_fill, cond_col_dict, args.exclude_orphans)
121
+ df_B = gapfill_on_media(logger, model, universe, dbexp, args.gapfill, cond_col_dict, args.excludeorp)
118
122
  if type(df_B)==int: return 1
119
123
 
120
124
  # force removal of reactions
121
- setattr(args, 'force_removal', '-') # experimental feature, not public. It's main purpose was to test gap-filling in biolog_on_media().
122
- remove_forced(logger, model, universe, args.force_removal)
125
+ setattr(args, 'remove', '-') # experimental feature, not public. It's main purpose was to test gap-filling in biolog_on_media().
126
+ remove_forced(logger, model, universe, args.remove)
123
127
 
124
128
  # perform Biolog(R) curation based on media
125
- df_P = biolog_on_media(logger, model, universe, dbexp, args.gap_fill, args.biolog, args.exclude_orphans, args.cnps)
129
+ df_P = biolog_on_media(logger, model, universe, dbexp, args.gapfill, args.biolog, args.excludeorp, args.cnps)
126
130
  if type(df_P)==int: return 1
127
131
 
128
132
 
@@ -142,12 +146,12 @@ def create_model_incore(params):
142
146
 
143
147
 
144
148
 
145
- ###### CHECKS
149
+ ###### CHECKS 1
146
150
  # check erroneous EGCs
147
151
  verify_egc_all(logger, model, args.outdir)
148
152
 
149
153
  # check blocked metabolites / dead-ends
150
- df_S = biosynthesis_on_media(logger, model, dbexp, args.gap_fill, args.biosynth)
154
+ df_S = biosynthesis_on_media(logger, model, dbexp, args.gapfill, args.biosynth)
151
155
  if type(df_S)==int: return 1
152
156
 
153
157
 
@@ -155,6 +159,16 @@ def create_model_incore(params):
155
159
  ###### POLISHING 3
156
160
  # reset growth environment befor saving the model
157
161
  gempipe.reset_growth_env(model)
162
+
163
+ # initialize model
164
+ response = initialize_model(logger, model, dbexp, args.initialize, args.gapfill)
165
+ if response==1: return 1
166
+
167
+
168
+
169
+ ###### CHECKS 2
170
+ # compute Memote metrics
171
+ memote_results_dict = get_memote_results_dict(logger, model)
158
172
 
159
173
 
160
174
 
@@ -165,7 +179,7 @@ def create_model_incore(params):
165
179
  cobra.io.write_sbml_model(model, f'{args.outdir}/{model.id}.xml') # SBML # groups are saved only to SBML
166
180
  logger.info(f"'{args.outdir}/{model.id}.xml' created!")
167
181
  force_id_on_sbml(f'{args.outdir}/{model.id}.xml', model.id) # force introduction of the 'id=""' field
168
- sheets_dict = write_excel_model(model, f'{args.outdir}/{model.id}.mkmodel.xlsx', args.nofigs, None, df_B, df_P, df_S)
182
+ sheets_dict = write_excel_model(model, f'{args.outdir}/{model.id}.mkmodel.xlsx', args.nofigs, memote_results_dict, None, df_B, df_P, df_S)
169
183
  logger.info(f"'{args.outdir}/{model.id}.mkmodel.xlsx' created!")
170
184
 
171
185
 
@@ -18,6 +18,9 @@ from ..commons import adjust_biomass_precursors
18
18
  from ..commons import count_undrawn_rids
19
19
  from ..commons import format_expansion
20
20
  from ..commons import download_keggorg
21
+ from ..commons import initialize_model
22
+ from ..commons import get_memote_results_dict
23
+
21
24
 
22
25
  from .introduce import introduce_metabolites
23
26
  from .introduce import introduce_reactions
@@ -178,41 +181,56 @@ def main(args, logger):
178
181
  # check erroneous EGCs
179
182
  verify_egc_all(logger, universe, args.outdir)
180
183
 
181
- # check growth on minmal media
182
- df_G = grow_on_media(logger, universe, dbexp, args.media, '-', True)
183
- if type(df_G)==int: return 1
184
184
 
185
- # check blocked biomass precursors
186
- cond_col_dict = adjust_biomass_precursors(logger, universe, universe, 1.0)
187
- df_E = precursors_on_media(logger, universe, universe, dbexp, args.media, cond_col_dict, args.precursors)
188
- if type(df_E)==int: return 1
185
+ if not args.justparse:
186
+
187
+
188
+ ###### CHECKS 3
189
+ # check growth on minmal media
190
+ df_G = grow_on_media(logger, universe, dbexp, args.media, '-', True)
191
+ if type(df_G)==int: return 1
189
192
 
190
- # check blocked metabolites / dead-ends
191
- df_S = biosynthesis_on_media(logger, universe, dbexp, args.media, args.biosynth)
192
- if type(df_S)==int: return 1
193
+ # check blocked biomass precursors
194
+ cond_col_dict = adjust_biomass_precursors(logger, universe, universe, 1.0)
195
+ df_E = precursors_on_media(logger, universe, universe, dbexp, args.media, cond_col_dict, args.precursors)
196
+ if type(df_E)==int: return 1
197
+
198
+ # check blocked metabolites / dead-ends
199
+ df_S = biosynthesis_on_media(logger, universe, dbexp, args.media, args.biosynth)
200
+ if type(df_S)==int: return 1
193
201
 
194
202
 
195
203
 
196
- ###### POLISHING 2
197
- # reset growth environment befor saving the model
198
- gempipe.reset_growth_env(universe)
199
-
204
+ ###### POLISHING 2
205
+ # reset growth environment befor saving the model
206
+ gempipe.reset_growth_env(universe)
207
+
208
+ # initialize model
209
+ response = initialize_model(logger, universe, dbexp, args.initialize, args.media)
210
+ if response==1: return 1
211
+
212
+
213
+
214
+ ###### CHECKS 4
215
+ # compute Memote metrics
216
+ memote_results_dict = get_memote_results_dict(logger, universe)
217
+
200
218
 
201
219
 
202
- # output the universe
203
- logger.info("Writing universal model...")
204
- cobra.io.save_json_model(universe, f'{args.outdir}/universe.json')
205
- logger.info(f"'{args.outdir}/universe.json' created!")
206
- cobra.io.write_sbml_model(universe, f'{args.outdir}/universe.xml') # groups are saved only to SBML
207
- logger.info(f"'{args.outdir}/universe.xml' created!")
208
- force_id_on_sbml(f'{args.outdir}/universe.xml', 'universe') # force introduction of the 'id=""' field
209
- sheets_dict = write_excel_model(universe, f'{args.outdir}/universe.parsedb.xlsx', args.nofigs, df_E, None, None, df_S, df_C)
210
- logger.info(f"'{args.outdir}/universe.parsedb.xlsx' created!")
220
+ # output the universe
221
+ logger.info("Writing universal model...")
222
+ cobra.io.save_json_model(universe, f'{args.outdir}/universe.json')
223
+ logger.info(f"'{args.outdir}/universe.json' created!")
224
+ cobra.io.write_sbml_model(universe, f'{args.outdir}/universe.xml') # groups are saved only to SBML
225
+ logger.info(f"'{args.outdir}/universe.xml' created!")
226
+ force_id_on_sbml(f'{args.outdir}/universe.xml', 'universe') # force introduction of the 'id=""' field
227
+ sheets_dict = write_excel_model(universe, f'{args.outdir}/universe.parsedb.xlsx', args.nofigs, memote_results_dict, df_E, None, None, df_S, df_C)
228
+ logger.info(f"'{args.outdir}/universe.parsedb.xlsx' created!")
211
229
 
212
230
 
213
231
 
214
- ###### CHECKS 3
215
- # check if universal escher map os updated:
232
+ ###### CHECKS 4
233
+ # check if universal escher map is updated:
216
234
  count_undrawn_rids(logger, universe, lastmap)
217
235
 
218
236
 
gsrap/parsedb/parsedb.py CHANGED
@@ -18,6 +18,9 @@ from ..commons import adjust_biomass_precursors
18
18
  from ..commons import count_undrawn_rids
19
19
  from ..commons import format_expansion
20
20
  from ..commons import download_keggorg
21
+ from ..commons import initialize_model
22
+ from ..commons import get_memote_results_dict
23
+
21
24
 
22
25
  from .introduce import introduce_metabolites
23
26
  from .introduce import introduce_reactions
@@ -178,41 +181,56 @@ def main(args, logger):
178
181
  # check erroneous EGCs
179
182
  verify_egc_all(logger, universe, args.outdir)
180
183
 
181
- # check growth on minmal media
182
- df_G = grow_on_media(logger, universe, dbexp, args.media, '-', True)
183
- if type(df_G)==int: return 1
184
184
 
185
- # check blocked biomass precursors
186
- cond_col_dict = adjust_biomass_precursors(logger, universe, universe, 1.0)
187
- df_E = precursors_on_media(logger, universe, universe, dbexp, args.media, cond_col_dict, args.precursors)
188
- if type(df_E)==int: return 1
185
+ if not args.justparse:
186
+
187
+
188
+ ###### CHECKS 3
189
+ # check growth on minmal media
190
+ df_G = grow_on_media(logger, universe, dbexp, args.media, '-', True)
191
+ if type(df_G)==int: return 1
189
192
 
190
- # check blocked metabolites / dead-ends
191
- df_S = biosynthesis_on_media(logger, universe, dbexp, args.media, args.biosynth)
192
- if type(df_S)==int: return 1
193
+ # check blocked biomass precursors
194
+ cond_col_dict = adjust_biomass_precursors(logger, universe, universe, 1.0)
195
+ df_E = precursors_on_media(logger, universe, universe, dbexp, args.media, cond_col_dict, args.precursors)
196
+ if type(df_E)==int: return 1
197
+
198
+ # check blocked metabolites / dead-ends
199
+ df_S = biosynthesis_on_media(logger, universe, dbexp, args.media, args.biosynth)
200
+ if type(df_S)==int: return 1
193
201
 
194
202
 
195
203
 
196
- ###### POLISHING 2
197
- # reset growth environment befor saving the model
198
- gempipe.reset_growth_env(universe)
199
-
204
+ ###### POLISHING 2
205
+ # reset growth environment befor saving the model
206
+ gempipe.reset_growth_env(universe)
207
+
208
+ # initialize model
209
+ response = initialize_model(logger, universe, dbexp, args.initialize, args.media)
210
+ if response==1: return 1
211
+
212
+
213
+
214
+ ###### CHECKS 4
215
+ # compute Memote metrics
216
+ memote_results_dict = get_memote_results_dict(logger, universe)
217
+
200
218
 
201
219
 
202
- # output the universe
203
- logger.info("Writing universal model...")
204
- cobra.io.save_json_model(universe, f'{args.outdir}/universe.json')
205
- logger.info(f"'{args.outdir}/universe.json' created!")
206
- cobra.io.write_sbml_model(universe, f'{args.outdir}/universe.xml') # groups are saved only to SBML
207
- logger.info(f"'{args.outdir}/universe.xml' created!")
208
- force_id_on_sbml(f'{args.outdir}/universe.xml', 'universe') # force introduction of the 'id=""' field
209
- sheets_dict = write_excel_model(universe, f'{args.outdir}/universe.parsedb.xlsx', args.nofigs, df_E, None, None, df_S, df_C)
210
- logger.info(f"'{args.outdir}/universe.parsedb.xlsx' created!")
220
+ # output the universe
221
+ logger.info("Writing universal model...")
222
+ cobra.io.save_json_model(universe, f'{args.outdir}/universe.json')
223
+ logger.info(f"'{args.outdir}/universe.json' created!")
224
+ cobra.io.write_sbml_model(universe, f'{args.outdir}/universe.xml') # groups are saved only to SBML
225
+ logger.info(f"'{args.outdir}/universe.xml' created!")
226
+ force_id_on_sbml(f'{args.outdir}/universe.xml', 'universe') # force introduction of the 'id=""' field
227
+ sheets_dict = write_excel_model(universe, f'{args.outdir}/universe.parsedb.xlsx', args.nofigs, memote_results_dict, df_E, None, None, df_S, df_C)
228
+ logger.info(f"'{args.outdir}/universe.parsedb.xlsx' created!")
211
229
 
212
230
 
213
231
 
214
- ###### CHECKS 3
215
- # check if universal escher map os updated:
232
+ ###### CHECKS 4
233
+ # check if universal escher map is updated:
216
234
  count_undrawn_rids(logger, universe, lastmap)
217
235
 
218
236
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: gsrap
3
- Version: 0.8.1
3
+ Version: 0.8.2
4
4
  Summary:
5
5
  License: GNU General Public License v3.0
6
6
  Author: Gioele Lazzari
@@ -1,5 +1,5 @@
1
- gsrap/.ipynb_checkpoints/__init__-checkpoint.py,sha256=lOurIE_Gn0jYS3ks3UmX11uuMrMScHADH9ivFoLpg5k,14160
2
- gsrap/__init__.py,sha256=lOurIE_Gn0jYS3ks3UmX11uuMrMScHADH9ivFoLpg5k,14160
1
+ gsrap/.ipynb_checkpoints/__init__-checkpoint.py,sha256=o4xMVuraz_Qnf6ZOtxcYjNl-a7-zlRuZsP-GEw8lP4I,15240
2
+ gsrap/__init__.py,sha256=o4xMVuraz_Qnf6ZOtxcYjNl-a7-zlRuZsP-GEw8lP4I,15240
3
3
  gsrap/assets/.ipynb_checkpoints/PM1-checkpoint.csv,sha256=0qjaMVG_t9aFxbHbxON6ecmEUnWPwN9nhmxc61QFeCU,8761
4
4
  gsrap/assets/.ipynb_checkpoints/PM2A-checkpoint.csv,sha256=rjYTdwe8lpRS552BYiUP3J71juG2ywVdR5Sux6fjZTY,8816
5
5
  gsrap/assets/.ipynb_checkpoints/PM3B-checkpoint.csv,sha256=42IGX_2O5bRYSiHoMuVKT-T-bzVj0cSRZBvGOrbnQMA,8130
@@ -11,30 +11,32 @@ gsrap/assets/PM4A.csv,sha256=f_5__0Ap_T0KYje5h9veW29I2qB4yU0h7Hr7WpaHjSc,9081
11
11
  gsrap/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  gsrap/assets/kegg_compound_to_others.pickle,sha256=pz1897cfQ7PLsYZiBVcoMQPzvRzT-nHUdgphBe0g5ZQ,8233860
13
13
  gsrap/assets/kegg_reaction_to_others.pickle,sha256=AGW8CGN5hKeXZoYn3JRF4Xu832WyNrTlMcLw7luttlc,1703146
14
- gsrap/commons/.ipynb_checkpoints/__init__-checkpoint.py,sha256=QuHINLSWNb0XKagHRWXzU5UVxw3ECTncvR7llRKblso,241
14
+ gsrap/commons/.ipynb_checkpoints/__init__-checkpoint.py,sha256=9lrb0sBFSWEgV_e5FYzSgjTbam8b959rW_8VuxQHt1M,268
15
15
  gsrap/commons/.ipynb_checkpoints/biomass-checkpoint.py,sha256=4u7WBaUgo42tBoXDU1D0VUjICatb44e0jfswZrBeHYs,17987
16
16
  gsrap/commons/.ipynb_checkpoints/coeffs-checkpoint.py,sha256=qI3_GuqHkeA2KbK9pYdkqJaFwYemAVZJGLRR4QtHt6w,19182
17
17
  gsrap/commons/.ipynb_checkpoints/downloads-checkpoint.py,sha256=e-7ffMD4R07MWEgXyGcwjhScbWnG7A3L100YWbpNMk0,8461
18
18
  gsrap/commons/.ipynb_checkpoints/escherutils-checkpoint.py,sha256=_y0TgM0-Im0RT8W8z5rr4vlnGK55iRFds6DlDsjGD-8,1151
19
- gsrap/commons/.ipynb_checkpoints/excelhub-checkpoint.py,sha256=zFTR6H7I3XeAt9_ORL0dfrwMRvshU3JPRmGif7fSY7w,7971
19
+ gsrap/commons/.ipynb_checkpoints/excelhub-checkpoint.py,sha256=1KemKQ5oWziFlrT3__70-AKjXwdsqwEzVswEOSbNBDs,11433
20
20
  gsrap/commons/.ipynb_checkpoints/figures-checkpoint.py,sha256=IRHSQXrCi4SQoISEfNB0rDhvUzbjcgsPi9zUSefsRto,4316
21
21
  gsrap/commons/.ipynb_checkpoints/fluxbal-checkpoint.py,sha256=jgC3-vI9Tbjvqohh2mJwFra4rl_pbUzHWrSa_QAxVO4,1262
22
22
  gsrap/commons/.ipynb_checkpoints/keggutils-checkpoint.py,sha256=M2nhHRiNH_xObHSxOIdt7ix59MrPdl9q3HNICC8X36M,4514
23
23
  gsrap/commons/.ipynb_checkpoints/logutils-checkpoint.py,sha256=VsnrkIsUftS3MOOwAd0n0peQ7a2X5ZEx930eCtzmW7g,1317
24
- gsrap/commons/.ipynb_checkpoints/medium-checkpoint.py,sha256=wcWiuZ-mqryoYBrsIHkIen6fBssR_1FGVoXUTApylNc,2901
24
+ gsrap/commons/.ipynb_checkpoints/medium-checkpoint.py,sha256=AMj95IvyWpbqKAYW5QdG_pyFXHDllUZ-b8dAsPR7tvU,3859
25
+ gsrap/commons/.ipynb_checkpoints/memoteutils-checkpoint.py,sha256=rulJFSVX4I-XGi4uHXloL0eGIkC5zhpuJYWJn9zCDbY,4981
25
26
  gsrap/commons/.ipynb_checkpoints/metrics-checkpoint.py,sha256=gvqF2c0e31m5qQWQ11JF4-eMqxtuONy_7lUiC7uaXX4,3291
26
27
  gsrap/commons/.ipynb_checkpoints/sbmlutils-checkpoint.py,sha256=gkY02qbGXrbYStn2F8J0KM0fmqati2Nbvi128EF7coI,365
27
- gsrap/commons/__init__.py,sha256=QuHINLSWNb0XKagHRWXzU5UVxw3ECTncvR7llRKblso,241
28
+ gsrap/commons/__init__.py,sha256=9lrb0sBFSWEgV_e5FYzSgjTbam8b959rW_8VuxQHt1M,268
28
29
  gsrap/commons/biomass.py,sha256=4u7WBaUgo42tBoXDU1D0VUjICatb44e0jfswZrBeHYs,17987
29
30
  gsrap/commons/coeffs.py,sha256=qI3_GuqHkeA2KbK9pYdkqJaFwYemAVZJGLRR4QtHt6w,19182
30
31
  gsrap/commons/downloads.py,sha256=e-7ffMD4R07MWEgXyGcwjhScbWnG7A3L100YWbpNMk0,8461
31
32
  gsrap/commons/escherutils.py,sha256=_y0TgM0-Im0RT8W8z5rr4vlnGK55iRFds6DlDsjGD-8,1151
32
- gsrap/commons/excelhub.py,sha256=zFTR6H7I3XeAt9_ORL0dfrwMRvshU3JPRmGif7fSY7w,7971
33
+ gsrap/commons/excelhub.py,sha256=1KemKQ5oWziFlrT3__70-AKjXwdsqwEzVswEOSbNBDs,11433
33
34
  gsrap/commons/figures.py,sha256=IRHSQXrCi4SQoISEfNB0rDhvUzbjcgsPi9zUSefsRto,4316
34
35
  gsrap/commons/fluxbal.py,sha256=jgC3-vI9Tbjvqohh2mJwFra4rl_pbUzHWrSa_QAxVO4,1262
35
36
  gsrap/commons/keggutils.py,sha256=M2nhHRiNH_xObHSxOIdt7ix59MrPdl9q3HNICC8X36M,4514
36
37
  gsrap/commons/logutils.py,sha256=VsnrkIsUftS3MOOwAd0n0peQ7a2X5ZEx930eCtzmW7g,1317
37
- gsrap/commons/medium.py,sha256=wcWiuZ-mqryoYBrsIHkIen6fBssR_1FGVoXUTApylNc,2901
38
+ gsrap/commons/medium.py,sha256=AMj95IvyWpbqKAYW5QdG_pyFXHDllUZ-b8dAsPR7tvU,3859
39
+ gsrap/commons/memoteutils.py,sha256=rulJFSVX4I-XGi4uHXloL0eGIkC5zhpuJYWJn9zCDbY,4981
38
40
  gsrap/commons/metrics.py,sha256=gvqF2c0e31m5qQWQ11JF4-eMqxtuONy_7lUiC7uaXX4,3291
39
41
  gsrap/commons/sbmlutils.py,sha256=gkY02qbGXrbYStn2F8J0KM0fmqati2Nbvi128EF7coI,365
40
42
  gsrap/getmaps/.ipynb_checkpoints/__init__-checkpoint.py,sha256=L4gLwk1vgnPlQuIP-FPnvy9uXnmGVQ4Rvjv3uyciDfk,92
@@ -47,14 +49,14 @@ gsrap/mkmodel/.ipynb_checkpoints/__init__-checkpoint.py,sha256=PNze-26HMOwfdJ92K
47
49
  gsrap/mkmodel/.ipynb_checkpoints/biologcuration-checkpoint.py,sha256=Nn7z-js-mzzeO23kVM2L7sJ5PNle7AkCUeBcEAYjlFU,15378
48
50
  gsrap/mkmodel/.ipynb_checkpoints/gapfill-checkpoint.py,sha256=BPZw4sszlBhAYfHnV0pA7EpG0b2ePwS6kUfFt0Ww-ss,5159
49
51
  gsrap/mkmodel/.ipynb_checkpoints/gapfillutils-checkpoint.py,sha256=S6nFUZ1Bbdf13nVJhGK2S5C_V3hd5zwTg2o5nzejngg,3123
50
- gsrap/mkmodel/.ipynb_checkpoints/mkmodel-checkpoint.py,sha256=3o4_B3ALcq6GYLAZ7zteNOcLTfE3KVJO6s9L4uMmw8E,10448
52
+ gsrap/mkmodel/.ipynb_checkpoints/mkmodel-checkpoint.py,sha256=zm-JA2sXwqTLalCc0L5POw2iRI56QK0UJMUgorHQrLw,10830
51
53
  gsrap/mkmodel/.ipynb_checkpoints/polishing-checkpoint.py,sha256=R1UdFPxN8N27Iu0jsYW2N_1BkWEbBHaMYW6NkCYZK_k,3256
52
54
  gsrap/mkmodel/.ipynb_checkpoints/pruner-checkpoint.py,sha256=FAZid-0H6j66wR2dVKRAaMaDREVt1edflmZXbX7blXg,9836
53
55
  gsrap/mkmodel/__init__.py,sha256=PNze-26HMOwfdJ92KiXpr--VV1ftVfo3CAxBZgeokp8,92
54
56
  gsrap/mkmodel/biologcuration.py,sha256=Nn7z-js-mzzeO23kVM2L7sJ5PNle7AkCUeBcEAYjlFU,15378
55
57
  gsrap/mkmodel/gapfill.py,sha256=BPZw4sszlBhAYfHnV0pA7EpG0b2ePwS6kUfFt0Ww-ss,5159
56
58
  gsrap/mkmodel/gapfillutils.py,sha256=S6nFUZ1Bbdf13nVJhGK2S5C_V3hd5zwTg2o5nzejngg,3123
57
- gsrap/mkmodel/mkmodel.py,sha256=3o4_B3ALcq6GYLAZ7zteNOcLTfE3KVJO6s9L4uMmw8E,10448
59
+ gsrap/mkmodel/mkmodel.py,sha256=zm-JA2sXwqTLalCc0L5POw2iRI56QK0UJMUgorHQrLw,10830
58
60
  gsrap/mkmodel/polishing.py,sha256=R1UdFPxN8N27Iu0jsYW2N_1BkWEbBHaMYW6NkCYZK_k,3256
59
61
  gsrap/mkmodel/pruner.py,sha256=FAZid-0H6j66wR2dVKRAaMaDREVt1edflmZXbX7blXg,9836
60
62
  gsrap/parsedb/.ipynb_checkpoints/__init__-checkpoint.py,sha256=1k2K1gz4lIdXAwHEdJ0OhdkPu83woGv0Z4TpT1kGrTk,97
@@ -63,7 +65,7 @@ gsrap/parsedb/.ipynb_checkpoints/completeness-checkpoint.py,sha256=yhFiEslK1qmMC
63
65
  gsrap/parsedb/.ipynb_checkpoints/cycles-checkpoint.py,sha256=HJ58LcHQseQ1eploysfXd5Y8Rip8n62qhje4pmL22VM,4761
64
66
  gsrap/parsedb/.ipynb_checkpoints/introduce-checkpoint.py,sha256=UuwGWGB2saG9VDMoboumeRBWhHOO68bs5_1r2RSkyVo,17145
65
67
  gsrap/parsedb/.ipynb_checkpoints/manual-checkpoint.py,sha256=qMKYshVftSGCRAjHC87E6n9-6kAiffFFCgHOUbqlyC0,3625
66
- gsrap/parsedb/.ipynb_checkpoints/parsedb-checkpoint.py,sha256=M44zFmaYu50LYDjFH3IdiezjPbzuDIzZ9ukzwU4ZBBM,7583
68
+ gsrap/parsedb/.ipynb_checkpoints/parsedb-checkpoint.py,sha256=fTZlQvjV_wyRIxWJbW5TCVvydn0-CsYknsx9FYspdu8,8127
67
69
  gsrap/parsedb/.ipynb_checkpoints/repeating-checkpoint.py,sha256=WwPOzlZgsZWmJ-rvhFg21iOJ6gajgKFc2vCIHh6weBg,6103
68
70
  gsrap/parsedb/__init__.py,sha256=1k2K1gz4lIdXAwHEdJ0OhdkPu83woGv0Z4TpT1kGrTk,97
69
71
  gsrap/parsedb/annotation.py,sha256=Y02_zXJj_tS1GyBdfuLBy9YJjMgx3mjX6tqr1KhQ-9Q,4810
@@ -71,7 +73,7 @@ gsrap/parsedb/completeness.py,sha256=yhFiEslK1qmMCk_GWZ7UZtX02FUqLU39UafG5886WsY
71
73
  gsrap/parsedb/cycles.py,sha256=HJ58LcHQseQ1eploysfXd5Y8Rip8n62qhje4pmL22VM,4761
72
74
  gsrap/parsedb/introduce.py,sha256=UuwGWGB2saG9VDMoboumeRBWhHOO68bs5_1r2RSkyVo,17145
73
75
  gsrap/parsedb/manual.py,sha256=qMKYshVftSGCRAjHC87E6n9-6kAiffFFCgHOUbqlyC0,3625
74
- gsrap/parsedb/parsedb.py,sha256=M44zFmaYu50LYDjFH3IdiezjPbzuDIzZ9ukzwU4ZBBM,7583
76
+ gsrap/parsedb/parsedb.py,sha256=fTZlQvjV_wyRIxWJbW5TCVvydn0-CsYknsx9FYspdu8,8127
75
77
  gsrap/parsedb/repeating.py,sha256=WwPOzlZgsZWmJ-rvhFg21iOJ6gajgKFc2vCIHh6weBg,6103
76
78
  gsrap/runsims/.ipynb_checkpoints/__init__-checkpoint.py,sha256=6E6E1gWgH0V7ls4Omx4mxxC85gMJ_27YqhjugJzlZtY,97
77
79
  gsrap/runsims/.ipynb_checkpoints/biosynth-checkpoint.py,sha256=fUlHUo4CfB4rGX9Dth87B1p5E5sz7i6spR7ZoqDDGaI,2836
@@ -91,8 +93,8 @@ gsrap/runsims/precursors.py,sha256=1RNt_Rxs0L1lolDmYh4_CiZgiwHfU5B_AcomJO6vJ28,2
91
93
  gsrap/runsims/runsims.py,sha256=2FC5Gs8oSYyZTjHF3A7aXB_O6myVfcn3bCxQfLJlZTk,2842
92
94
  gsrap/runsims/simplegrowth.py,sha256=tCQHTMUqum1YwlBKRTNaQoag2co_yQlCaKmISOARAlE,2353
93
95
  gsrap/runsims/singleomission.py,sha256=jMuKAi0pINP8Jlrm-yI-tX7D110VzttR3YfTSnDRe4I,2847
94
- gsrap-0.8.1.dist-info/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
95
- gsrap-0.8.1.dist-info/METADATA,sha256=TvK87lEyotFJA3LRgzVFROv7mHMya-p0xPv5EUQNUJE,898
96
- gsrap-0.8.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
97
- gsrap-0.8.1.dist-info/entry_points.txt,sha256=S9MY0DjfnbKGlZbp5bV7W6dNFy3APoEV84u9x6MV1eI,36
98
- gsrap-0.8.1.dist-info/RECORD,,
96
+ gsrap-0.8.2.dist-info/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
97
+ gsrap-0.8.2.dist-info/METADATA,sha256=CEZpXejZ1b_KWKhxPbSXKGdW01ZU_nkKFqzfafDXXGE,898
98
+ gsrap-0.8.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
99
+ gsrap-0.8.2.dist-info/entry_points.txt,sha256=S9MY0DjfnbKGlZbp5bV7W6dNFy3APoEV84u9x6MV1eI,36
100
+ gsrap-0.8.2.dist-info/RECORD,,
File without changes