Skip to content

Commit 8793ac3

Browse files
FarnazmdiaarmeyAaron Meyerclaude
authored
Plot population level from lineage data (#988)
* not yet complete * some more edits * finish * add gemcitabine * Delete output/figure0.svg * Fix figure0.py for LineageTree array refactor, remove taxol loaders figure0.py used the pre-refactor get_leaves_idx() helper, which no longer exists after the CSR sparse array rework; switch to the lin.leaves_idx attribute instead. The taxol loading code (import_taxol* / assign_observs_Taxol / sep_lineages in import_lineage.py, and the taxol block in Lineage_collections.py) depended on lineage/data/taxol/, which is gitignored and not available, breaking every import of Lineage_collections. Remove it along with figureS18.py/figureS19.py, the only figures that depended on it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XBehA2a1Zp2n2ce8Vr1ATa * Bump CI actions to Node 24 runtime, silence deprecation warning actions/checkout@v4 and astral-sh/setup-uv@v5 both target Node 20, which GitHub Actions runners are deprecating; bump to actions/checkout@v7 and astral-sh/setup-uv@v10, which target Node 24. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XBehA2a1Zp2n2ce8Vr1ATa * Fix setup-uv version pin, no v10 floating tag exists astral-sh/setup-uv only publishes exact version tags for v8+ (no v10 alias), unlike actions/checkout; pin to v10.0.1 explicitly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XBehA2a1Zp2n2ce8Vr1ATa --------- Co-authored-by: Aaron Meyer <2065146+aarmey@users.noreply.github.com> Co-authored-by: Aaron Meyer <git@ameyer.me> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 0432557 commit 8793ac3

6 files changed

Lines changed: 107 additions & 398 deletions

File tree

‎.github/workflows/pytest.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ jobs:
66
build:
77
runs-on: ubuntu-latest
88
steps:
9-
- uses: actions/checkout@v4
9+
- uses: actions/checkout@v7
1010
- name: Setup submodule
1111
run: git submodule update --init --recursive
1212
- name: Install uv
13-
uses: astral-sh/setup-uv@v5
13+
uses: astral-sh/setup-uv@v10.0.1
1414
- name: Install dependencies
1515
run: uv sync
1616
- name: Lint with ruff

‎lineage/Lineage_collections.py‎

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""This file is to collect those lineages that have the same condition, and have 3 or greater number of cells in their lineages."""
22

3-
from .import_lineage import MCF10A, import_taxol
3+
from .import_lineage import MCF10A
44
from .LineageInputOutput import import_exp_data
55
from .LineageTree import LineageTree
66
from .states.StateDistributionGamma import StateDistribution as StDist
@@ -153,15 +153,3 @@ def load_replicate_groups(replicate_file_groups: list[list[str]]):
153153
AllLapatinib = [Lapatinib_Control + Gemcitabine_Control, Lapt25uM, Lapt50uM, Lap250uM]
154154
AllGemcitabine = [Lapatinib_Control + Gemcitabine_Control, Gem5uM, Gem10uM, Gem30uM]
155155
GFs = [pbs, egf, hgf, osm]
156-
157-
##########################################################
158-
# NEW PACLITAXEL DATA
159-
untreated, taxol_05, taxol_1, taxol_15, taxol_2, taxol_25, taxol_3, taxol_4 = import_taxol()
160-
# 555, 1119, 486, 382, 272, 365, 246, 266
161-
untreated_taxol = [LineageTree(list_cells, E) for list_cells in untreated] # 555 cells
162-
Taxol_1 = [LineageTree(list_cells, E) for list_cells in taxol_1] # 486 cells
163-
Taxol_2 = [LineageTree(list_cells, E) for list_cells in taxol_2] # 272 cells
164-
Taxol_3 = [LineageTree(list_cells, E) for list_cells in taxol_3] # 246 cells
165-
Taxol_4 = [LineageTree(list_cells, E) for list_cells in taxol_4] # 266 cells
166-
167-
taxols = [untreated_taxol, Taxol_1, Taxol_2, Taxol_4]

‎lineage/figures/figure0.py‎

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""To plot population level of lapatinib from the lineage trees."""
2+
3+
import random
4+
5+
import numpy as np
6+
7+
from ..Lineage_collections import AllGemcitabine, AllLapatinib
8+
from .common import getSetup
9+
10+
11+
def makeFigure():
12+
"""
13+
Makes figure 1.
14+
"""
15+
# Get list of axis objects
16+
ax, f = getSetup((10, 6), (2, 4))
17+
18+
lpt = ["Lapatinib, 25", "Lapatinib, 50", "Lapatinib 250"]
19+
gmc = ["Gemcitabine, 5", "Gemcitabine, 10", "Gemcitabine, 30"]
20+
plot_each_drug(f, ax[:4], AllLapatinib, lpt)
21+
plot_each_drug(f, ax[4:], AllGemcitabine, gmc)
22+
return f
23+
24+
25+
def leaves_to_root(lin, ts):
26+
"""A function to traverse from root to leaves
27+
by randomly selecting a daughter cell at each generation forward,
28+
and calculate the time-series counts at G1 and S/G2."""
29+
counts = np.zeros((ts.size, 2)) # G1 and S/G2
30+
31+
t_cur = 0.0
32+
33+
# randomly choose one of leaf cells.
34+
leaves_idx = lin.leaves_idx
35+
lineage = lin.output_lineage
36+
random_leaf_idx = random.choice(leaves_idx)
37+
38+
cells = [lineage[random_leaf_idx]]
39+
40+
# traverse back to root from the randomly chosen leaf
41+
for c in cells:
42+
if c.parent is not None:
43+
cells.append(c.parent)
44+
45+
cells.reverse() # order from root to leaf
46+
47+
for ii, cell in enumerate(cells): # the number of generations
48+
for phase in range(2):
49+
gamma_obs = np.nan_to_num(cell.obs[phase + 2])
50+
idx = (ts > t_cur) & (ts < t_cur + gamma_obs)
51+
counts[idx, phase] += 2 ** (ii + 1)
52+
t_cur += gamma_obs
53+
return counts
54+
55+
56+
def plot_each_drug(f, ax, all_drug, name_list):
57+
control = all_drug[0]
58+
c1 = all_drug[1]
59+
c2 = all_drug[2]
60+
c3 = all_drug[3]
61+
62+
ts = np.arange(96, step=0.5)
63+
64+
Gs = leaves_to_root(control[0], ts)
65+
for lineage in control[1:]:
66+
Gs += leaves_to_root(lineage, ts)
67+
ax[0].plot(Gs[:, 0], label="G1")
68+
ax[0].plot(Gs[:, 1], label="SG2")
69+
ax[0].set_title("Untreated")
70+
ax[0].set_xlabel("Time [0.5hr]")
71+
ax[0].set_ylabel("Cell counts")
72+
ax[0].legend()
73+
74+
Gs1 = leaves_to_root(c1[0], ts)
75+
for lineage in c1[1:]:
76+
Gs1 += leaves_to_root(lineage, ts)
77+
ax[1].plot(Gs1[:, 0], label="G1")
78+
ax[1].plot(Gs1[:, 1], label="SG2")
79+
ax[1].set_title(name_list[0] + " nM")
80+
ax[1].set_xlabel("Time [0.5hr]")
81+
ax[1].set_ylabel("Cell counts")
82+
ax[1].legend()
83+
84+
Gs2 = leaves_to_root(c2[0], ts)
85+
for lineage in c2[1:]:
86+
Gs2 += leaves_to_root(lineage, ts)
87+
ax[2].plot(Gs2[:, 0], label="G1")
88+
ax[2].plot(Gs2[:, 1], label="SG2")
89+
ax[2].set_title(name_list[1] + " nM")
90+
ax[2].set_xlabel("Time [0.5hr]")
91+
ax[2].set_ylabel("Cell counts")
92+
ax[2].legend()
93+
94+
Gs3 = leaves_to_root(c3[0], ts)
95+
for lineage in c3[1:]:
96+
Gs3 += leaves_to_root(lineage, ts)
97+
ax[3].plot(Gs3[:, 0], label="G1")
98+
ax[3].plot(Gs3[:, 1], label="SG2")
99+
ax[3].set_title(name_list[2] + " nM")
100+
ax[3].set_xlabel("Time [0.5hr]")
101+
ax[3].set_ylabel("Cell counts")
102+
ax[3].legend()
103+
104+
f.tight_layout()

‎lineage/figures/figureS18.py‎

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

‎lineage/figures/figureS19.py‎

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

0 commit comments

Comments
 (0)