Skip to content

Commit 67bad67

Browse files
Creating paper plots and adding convenience methods
1 parent afe7dde commit 67bad67

11 files changed

Lines changed: 519 additions & 557 deletions

notebooks/linearity_analysis.ipynb

Lines changed: 6 additions & 6 deletions
Large diffs are not rendered by default.

scripts/evaluate_monomial_models.py

Lines changed: 0 additions & 111 deletions
This file was deleted.

scripts/make_paper_plots.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
'''Creates the plots used in the paper.'''
2+
3+
from src.biomodels_iterator import BiomodelsIterator
4+
import src.constants as cn
5+
from src.model import Model
6+
from src.score import Score
7+
from src.simulator import Simulator
8+
from src.system_discovery import SystemDiscovery, discoverNetwork
9+
from src.timecourse import Timecourse
10+
from src.timecourse_iterator import TimecourseIterator
11+
12+
IS_PLOT = False
13+
14+
import constants as cn
15+
if not IS_PLOT:
16+
import matplotlib # type: ignore
17+
matplotlib.use("PDF") # Use non-interactive backend for testing
18+
import matplotlib.pyplot as plt # type: ignore
19+
import numpy as np # type: ignore
20+
import os
21+
import pandas as pd # type: ignore
22+
from typing import Optional
23+
24+
NUM_POINT = 1000
25+
26+
############### Helper Functions####################
27+
28+
def doPlot(model_num: int, poly_degree=1, threshold=0.001, species_names: Optional[list[str]] = None,
29+
num_point:int=NUM_POINT):
30+
start_time = 0
31+
model = Model.makeBiomodel(model_num=model_num)
32+
timecourse = Timecourse(model, start_time=start_time, num_point=num_point)
33+
sdr = discoverNetwork(timecourse.timecourse_df, poly_degree=poly_degree, threshold=threshold,
34+
plot_species_names=species_names, is_plot=IS_PLOT, subtitle=f"BioModel {model_num}",
35+
is_plot_heatmap=False, is_print_equations=False, is_plot_comparisons=True, is_print_accuracy=False)
36+
return sdr
37+
38+
################################################
39+
# Linear Fits
40+
################################################
41+
############### Time course ####################
42+
sdr = doPlot(968, species_names=["SOCS1", "IL7IL7RJAK1"])
43+
sdr.fig.savefig(os.path.join(cn.PAPER_DIR, "linear_fit_968.pdf"), bbox_inches="tight", dpi=300) # type: ignore
44+
##
45+
sdr = doPlot(1004, species_names= ["IL6ext", "STAT3mRNA"])
46+
sdr.fig.savefig(os.path.join(cn.PAPER_DIR, "linear_fit_1004.pdf"), bbox_inches="tight", dpi=300) # type: ignore
47+
#
48+
############### CDFs ####################
49+
path = os.path.join(cn.DATA_DIR, "linear_predictor_scores-0.001.csv")
50+
score = Score.deserialize(path)
51+
fig = score.plotCDF(["min", "p10", "p50", "max"], xlabel= "model accuracy", is_plot_species=False,
52+
is_plot_model=True, title=f"BioModel Models").fig
53+
if IS_PLOT:
54+
plt.show()
55+
fig.savefig(os.path.join(cn.PAPER_DIR, "linear_fit_model_cdf.pdf"), bbox_inches="tight", dpi=300) # type: ignore
56+
#
57+
fig = score.plotCDF(["min", "p10", "p50", "max"], xlabel= "model accuracy", is_plot_species=True,
58+
is_plot_model=False, title=f"BioModel Species").fig
59+
fig.savefig(os.path.join(cn.PAPER_DIR, "linear_fit_species_cdf.pdf"), bbox_inches="tight", dpi=300) # type: ignore
60+
if IS_PLOT:
61+
plt.show()
62+
63+
################################################
64+
# Perturbations
65+
################################################
66+
############### Time course ####################
67+
apr = SystemDiscovery.analyzePerturbations(1004, perturbations=[-50, -10, 0, 10, 50], frac_scatter_skip=0.05,
68+
subtitle="BioModel 1004", plot_species_names=["IL6ext","IL6int"])
69+
apr.fig.savefig(os.path.join(cn.PAPER_DIR, "perturbation_fit_1004.pdf"), bbox_inches="tight", dpi=300) # type: ignore
70+
#
71+
apr = SystemDiscovery.analyzePerturbations(968, perturbations=[-50, -10, 0, 10, 50], frac_scatter_skip=0.05,
72+
subtitle=f"BioModel 968", plot_species_names= ["SOCS1", "IL7IL7RJAK1"])
73+
apr.fig.savefig(os.path.join(cn.PAPER_DIR, "perturbation_fit_968.pdf"), bbox_inches="tight", dpi=300) # type: ignore

scripts/perturbation_study.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
"""Perturbation study: how do perturbed initial conditions affect SystemDiscovery R²?
22
3-
Runs only on models whose deg1_min >= MIN_R2 in evaluate_monomial_models-0.01.csv.
3+
Runs only on models with a explicitly specified end time.
44
For each qualifying model, SystemDiscovery.analyzePerturbations is called with
55
perturbation_value_fractions of -50%, -20%, -10%, -5%, 0%, +5%, +10%, +20%, +50%.
66
R² is computed using the derivative method.
77
88
Output CSV: data/perturbation_study.csv
99
Columns: model_name, threshold, and for each perturbation level
10-
(r2_-50, r2_-20, r2_-10, r2_-05, r2_0, r2_+05, r2_+10, r2_+20, r2_+50):
11-
three columns _min, _med, _max (clamped derivative R² across species).
1210
"""
1311

1412
import os
@@ -62,15 +60,16 @@ def main(is_initialize: bool = False) -> pd.DataFrame:
6260
perturbation_species_fraction=SPECIES_FRACTION,
6361
poly_degree=POLY_DEGREE,
6462
is_plot=False,
65-
)
63+
).df
6664
except Exception as exc:
6765
print(f" [error] {item.model_name}: {exc}", file=sys.stderr)
6866
continue
6967

68+
analyze_df[cn.COL_THRESHOLD] = THRESHOLD
7069
current_df = pd.read_csv(OUTPUT_PATH) if os.path.isfile(OUTPUT_PATH) else pd.DataFrame()
7170
# Ensure analyze_df is a DataFrame before concatenating/writing.
7271
if isinstance(analyze_df, pd.Series):
73-
analyze_df = pd.DataFrame([analyze_df.to_dict()])
72+
analyze_df = pd.DataFrame([analyze_df.to_dict()]).df
7473
full_df = pd.concat([current_df, analyze_df], ignore_index=True) if len(current_df) > 0 else analyze_df
7574
full_df.to_csv(OUTPUT_PATH, index=False)
7675

src/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
TIMECOURSE_SERIALIZATION_DIR = os.path.join(SERIALIZATION_DIR,
1515
"timecourse")
1616
TIMECOURSE_ZIP_PATH = os.path.join(TIMECOURSE_SERIALIZATION_DIR, "timecourse.zip")
17+
PAPER_DIR = os.path.join(PROJECT_DIR, "paper")
1718

1819
# Types
1920
TYPE_ROADRUNNER = "tellurium.roadrunner.extended_roadrunner.ExtendedRoadRunner"
@@ -43,6 +44,7 @@
4344
COL_NAMES = [COL_MODEL_NAME, COL_MAXCV, COL_ENDTIME, COL_ENDTIME_SOURCE]
4445
COL_PERTURBATION = "perturbation" # Perturbation value fraction used in simulation
4546
COL_SYSTEM_ID = "system_id" # Unique identifier for the system, e.g. model name or species name.
47+
COL_THRESHOLD = "threshold" # Threshold used in SystemDiscovery
4648
COL_MEAN = "mean" # Mean value of the valid values used in calculating the statistics.
4749
COL_MIN = "min" # Minimum value of the valid values used in calculating the statistics.
4850
COL_MAX = "max" # Maximum value of the valid values used in calculating the statistics.

src/score.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -271,25 +271,25 @@ def doPlot(value_arr: np.ndarray):
271271
plot_options = PlotOptions(**kwargs)
272272
legend = []
273273
if is_plot_model:
274-
for metric_name in metric_names:
274+
for mname in metric_names:
275275
model_df = df[df[cn.COL_AGGREGATION_TYPE] == cn.COL_AGGREGATION_TYPE_MODEL]
276-
if not model_df.empty and metric_name in model_df.columns:
277-
legend.append(f"{metric_name} (model)")
278-
value_arr = np.array(model_df[metric_name].values)
276+
if not model_df.empty and mname in model_df.columns:
277+
legend.append(f"{mname} (model)")
278+
value_arr = np.array(model_df[mname].values)
279279
doPlot(value_arr)
280280
plotted_any = True
281281
else:
282-
missing_metrics.append(f"model: {metric_name}")
282+
missing_metrics.append(f"model: {mname}")
283283
if is_plot_species:
284-
for metric_name in metric_names:
284+
for mname in metric_names:
285285
species_df = df[df[cn.COL_AGGREGATION_TYPE] != cn.COL_AGGREGATION_TYPE_MODEL]
286-
if not species_df.empty and metric_name in species_df.columns:
287-
legend.append(f"{metric_name} (species)")
288-
value_arr = np.array(species_df[metric_name].values)
286+
if not species_df.empty and mname in species_df.columns:
287+
legend.append(f"{mname} (species)")
288+
value_arr = np.array(species_df[mname].values)
289289
doPlot(value_arr)
290290
plotted_any = True
291291
else:
292-
missing_metrics.append(f"species: {metric_name}")
292+
missing_metrics.append(f"species: {mname}")
293293
if len(missing_metrics) > 0:
294294
warnings.warn(f"No data found for metrics {missing_metrics}; nothing was plotted.", UserWarning)
295295
if not plotted_any:

0 commit comments

Comments
 (0)