Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
bd924b8
dtw w params
edyoshikun Sep 18, 2025
46eee60
test_demo cell cycle
edyoshikun Sep 15, 2025
2af108a
demo using embedding distances
edyoshikun Sep 15, 2025
7d5037f
cleanup CytoDtw and cell_cycle_consensus example
edyoshikun Sep 16, 2025
ccd19c7
consensus pattern standarization
edyoshikun Sep 16, 2025
5425c7d
modify the dtw to use a fixed step window size instead of a fraction
edyoshikun Sep 11, 2025
6bbda6b
update old compare_dtw_embeddings script ot use CytoDtw
edyoshikun Sep 4, 2025
e44e90e
update CytoDtw computing consensus track
edyoshikun Sep 4, 2025
1c33929
pseudotime plotting
edyoshikun Sep 3, 2025
a505448
adding the pseudotime
edyoshikun Sep 3, 2025
63cac45
adding the dtw functions
edyoshikun Sep 24, 2025
3fd3b23
fix cell_cycle_consensus to use the new dataset
edyoshikun Sep 24, 2025
dcf8a7e
save the consensus and annotations
edyoshikun Sep 25, 2025
4fc51bf
fix the bug with pseudotime start and end timepoints. Using tracks ti…
edyoshikun Sep 25, 2025
6af911b
proof of concept for aligning
edyoshikun Sep 25, 2025
0c2665c
fix saving the consensus as pkll
edyoshikun Sep 25, 2025
2f6456c
upgrade cytodtw to ann data
edyoshikun Sep 29, 2025
3c7a6c3
Merge branch 'main' into dtw_clean
edyoshikun Sep 29, 2025
2842fe3
support 1 annotation for the consensus.
edyoshikun Sep 30, 2025
b433a1d
infection_state file for 11_21
edyoshikun Sep 30, 2025
842ee38
fix the plotting and image sequence alignment
edyoshikun Sep 30, 2025
5114f46
remove redudant entries to the dict in the matches
edyoshikun Sep 30, 2025
dbd050b
moving useful functions to psedotime.py
edyoshikun Sep 30, 2025
b7b235b
moving plotting functions to pseudotime
edyoshikun Oct 1, 2025
9f527af
get track stats
edyoshikun Oct 1, 2025
edc3247
update the track stats to spit out markdown for confluence
edyoshikun Oct 1, 2025
4d3b9e9
add track_stasts computation for debugging
edyoshikun Oct 9, 2025
c2541e0
cleanup infection_state script
edyoshikun Oct 9, 2025
0dd1d16
add markers for infection annotation.
edyoshikun Oct 13, 2025
5e10fe6
update to use markers for infection
edyoshikun Oct 13, 2025
e4397ea
proof of concept for segmentation and extraction of features
edyoshikun Oct 14, 2025
0d5a46a
update folder output for demo file
edyoshikun Oct 14, 2025
6d2e5c9
code to generate the pandas dataframe per position
edyoshikun Oct 14, 2025
c2160c6
parallelized segment mito features
edyoshikun Oct 14, 2025
54e4cb0
simplify script for computing and visualizing
edyoshikun Oct 22, 2025
a8eb68a
Merge branch 'main' into dtw_clean
edyoshikun Oct 22, 2025
b61d03b
Merge branch 'main' into dtw_clean
edyoshikun Oct 24, 2025
746ee39
filter adata
edyoshikun Oct 27, 2025
eeda0c3
Merge branch 'main' into dtw_clean
edyoshikun Oct 28, 2025
a5d2b25
Merge branch 'main' into dtw_clean
edyoshikun Oct 28, 2025
30aafd8
Log the similarity between anchor and negatives (#332)
edyoshikun Nov 3, 2025
c591950
Implementation of Beta VAE for benchmarking (#273)
edyoshikun Nov 3, 2025
738d591
Merge remote-tracking branch 'origin/mito_seg' into dtw_clean
edyoshikun Nov 4, 2025
f75be6a
update to uset the segmetatins from biahub
edyoshikun Nov 5, 2025
22d94ce
Fix undefined variables in individual_with_mean plot type
edyoshikun Nov 8, 2025
9c632c7
cleanup
edyoshikun Nov 10, 2025
a977330
merge main
edyoshikun Nov 12, 2025
b6bb75a
add warping to the computation so we get all the sequences
edyoshikun Nov 13, 2025
7fbd17c
fix and plot everything in pseudotime
edyoshikun Nov 14, 2025
4ee77ff
fix visualization
edyoshikun Nov 15, 2025
273a7cd
duplicate phate random parameter causing error. (#341)
edyoshikun Nov 18, 2025
f476214
Merge branch 'main' into dtw_clean
edyoshikun Dec 10, 2025
b93c9de
Merge branch 'main' into dtw_clean
edyoshikun Dec 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
921 changes: 921 additions & 0 deletions applications/pseudotime_analysis/cell_cycle/cell_cycle_consensus.py

Large diffs are not rendered by default.

910 changes: 246 additions & 664 deletions applications/pseudotime_analysis/evaluation/compare_dtw_embeddings.py

Large diffs are not rendered by default.

154 changes: 154 additions & 0 deletions applications/pseudotime_analysis/get_tracking_stat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# %%
import logging
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from anndata import read_zarr

from viscy.representation.pseudotime import (
CytoDtw,
)

# %%
logger = logging.getLogger("viscy")
logger.setLevel(logging.INFO)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
formatter = logging.Formatter("%(message)s")
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)


features_path = "/hpc/projects/intracellular_dashboard/organelle_dynamics/2025_06_26_A549_G3BP1_ZIKV/4-phenotyping/predictions/anndata_predictions/phase_160patch_104ckpt_ver3max.zarr"
# %%
# Load AnnData directly
adata = read_zarr(features_path)
print("Loaded AnnData with shape:", adata.shape)
print("Available columns:", adata.obs.columns.tolist())

# Instantiate the CytoDtw object with AnnData
cytodtw = CytoDtw(adata)
feature_df = cytodtw.adata.obs

min_timepoints = 0
filtered_lineages = cytodtw.get_lineages(min_timepoints)

fov_stats = cytodtw.get_track_statistics(filtered_lineages, per_fov=True)
logger.info("\n=== Confluence Table Format ===")
logger.info(
"| FOV Name | Lineages | Total Tracks | Tracks/Lineage (mean ± std) | Total Timepoints/Lineage (mean ± std) | Timepoints/Track (mean ± std) |"
)
logger.info(
"|----------|----------|--------------|------------------------------|---------------------------------------|-------------------------------|"
)
for _, row in fov_stats.iterrows():
logger.info(
f"| {row['fov_name']} | {row['n_lineages']} | {row['total_tracks']} | "
f"{row['mean_tracks_per_lineage']:.2f} ± {row['std_tracks_per_lineage']:.2f} | "
f"{row['mean_total_timepoints']:.2f} ± {row['std_total_timepoints']:.2f} | "
f"{row['mean_timepoints_per_track']:.2f} ± {row['std_timepoints_per_track']:.2f} |"
)

logger.info("\n=== Global Statistics (All FOVs) ===")
min_t = adata.obs["t"].min()
max_t = adata.obs["t"].max()
n_timepoints = max_t - min_t + 1
global_lineages = fov_stats["n_lineages"].sum()
global_tracks = fov_stats["total_tracks"].sum()
logger.info(f"Total Timepoints: ({n_timepoints})")
logger.info(f"Total lineages: {global_lineages}")
logger.info(f"Total tracks: {global_tracks}")
logger.info(
f"Tracks per lineage (global): {fov_stats['mean_tracks_per_lineage'].mean():.2f} ± {fov_stats['mean_tracks_per_lineage'].std():.2f}"
)
logger.info(
f"Total timepoints per lineage (global): {fov_stats['mean_total_timepoints'].mean():.2f} ± {fov_stats['mean_total_timepoints'].std():.2f}"
)
logger.info(
f"Timepoints per track (global): {fov_stats['mean_timepoints_per_track'].mean():.2f} ± {fov_stats['mean_timepoints_per_track'].std():.2f}"
)

track_stats = cytodtw.get_track_statistics(filtered_lineages, per_fov=False)

# %%
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

axes[0, 0].hist(
track_stats["total_timepoints"],
bins=30,
color="#1f77b4",
alpha=0.7,
edgecolor="black",
)
axes[0, 0].axvline(
track_stats["total_timepoints"].mean(),
color="#ff7f0e",
linestyle="--",
linewidth=2,
label=f'Mean: {track_stats["total_timepoints"].mean():.1f}',
)
axes[0, 0].set_xlabel("Total Timepoints per Lineage")
axes[0, 0].set_ylabel("Count")
axes[0, 0].set_title("Distribution of Total Timepoints per Lineage")
axes[0, 0].legend()
axes[0, 0].grid(alpha=0.3)

axes[0, 1].hist(
track_stats["n_tracks"],
bins=range(1, int(track_stats["n_tracks"].max()) + 2),
color="#1f77b4",
alpha=0.7,
edgecolor="black",
)
axes[0, 1].axvline(
track_stats["n_tracks"].mean(),
color="#ff7f0e",
linestyle="--",
linewidth=2,
label=f'Mean: {track_stats["n_tracks"].mean():.2f}',
)
axes[0, 1].set_xlabel("Number of Tracks per Lineage")
axes[0, 1].set_ylabel("Count")
axes[0, 1].set_title("Distribution of Tracks per Lineage")
axes[0, 1].legend()
axes[0, 1].grid(alpha=0.3)

axes[1, 0].hist(
track_stats["mean_timepoints_per_track"],
bins=30,
color="#1f77b4",
alpha=0.7,
edgecolor="black",
)
axes[1, 0].axvline(
track_stats["mean_timepoints_per_track"].mean(),
color="#ff7f0e",
linestyle="--",
linewidth=2,
label=f'Mean: {track_stats["mean_timepoints_per_track"].mean():.1f}',
)
axes[1, 0].set_xlabel("Mean Timepoints per Track")
axes[1, 0].set_ylabel("Count")
axes[1, 0].set_title("Distribution of Mean Timepoints per Track")
axes[1, 0].legend()
axes[1, 0].grid(alpha=0.3)

axes[1, 1].scatter(
track_stats["n_tracks"],
track_stats["total_timepoints"],
alpha=0.6,
s=50,
color="#1f77b4",
edgecolor="black",
linewidth=0.5,
)
axes[1, 1].set_xlabel("Number of Tracks")
axes[1, 1].set_ylabel("Total Timepoints")
axes[1, 1].set_title("Tracks vs Total Timepoints")
axes[1, 1].grid(alpha=0.3)
plt.tight_layout()
plt.show()

# %%
Loading