This directory contains tools for detecting, tracking, and analyzing Ca²⁺ signaling waves in time-lapse microscopy images of embryos.
The pipeline processes multi-page TIFF images to:
- Detect bright Ca²⁺ "spark" events (GCaMP fluorescence signals)
- Track individual events across frames
- Segment embryos and compute anatomical coordinates (AP/DV axes)
- Generate per-frame and per-cluster summaries for downstream analysis
This follows the methodology described in:
- Shannon et al. 2017 (Biophys J): wound-induced Ca²⁺ signal dynamics
- Tung et al. 2024 (Nat Commun): inter-embryo injury waves in Xenopus laevis
-
wave-vector-tiff-parser.py: Main processing script that:- Reads TIFF files (supports multi-page, 16-bit images)
- Detects and tracks Ca²⁺ sparks frame-by-frame
- Automatically segments embryos and estimates head-tail axes
- Detects poke/injury sites (optional)
- Outputs
spark_tracks.csvwith per-frame measurements
-
spark_tracks_to_clusters.py: Aggregates per-frame data into per-cluster summaries- Converts
spark_tracks.csv→vector_clusters.csv - Computes speeds, path lengths, durations, directionality metrics
- Converts
-
visualize_spark_tracks.py: Visualization and analysis tools- Trajectory plots
- Speed/direction distributions
- Time series analysis
- Spatial heatmaps
- Per-embryo comparisons
-
generate_all_hypothesis_plots.py: Generate comprehensive plots for all testable hypotheses- Activity analysis with standard deviation
- Inter-embryo comparisons
- AP position analysis
- Speed vs time analysis
- All plots mapped to specific experimental hypotheses
-
generate_detection_summary.py: Manual-QA layer that renders per-video visual summaries (outlines, head/tail labels, poke locations) for verifying detection assumptions.
generate_pixel_brightness_vectors.py: Frame-by-frame dense motion of every bright pixel (each pixel in frame t matched to t−1 via KD-tree), on a linear brightness scale. Outputspixel_frame_deltas.csv.rollup_pixel_vectors_to_waves.py: Clusters the dense pixel deltas into per-frame "fronts" and links them across frames into coherent WAVE events (wave_events.csv: origin, duration, propagation speed, front speed).batch_wave_catalog.py: Runs the two steps above on every calcium video and aggregates into a singlewave_catalog.csv(tagged with stimulus / contact / orientation).wave_laterality_analysis.py: Splits the two embryos along the principal axis of their wave origins, labels the stimulated vs neighbor embryo, and scores neighbor-wave presence, neighbor local (front) speed, onset lag, and bidirectional spread per video →wave_laterality.csv.
create_embryo_masks.py,create_normalized_masks.py,create_size_constrained_masks.py: Generate / audit embryo segmentation masks for the parser.
embryo_region_map.py: Maps detected coordinates into named anatomical regions via a normalized reference map.embryo_units.py: Converts distances/speeds from pixels into embryo-relative units.
wave-vector.md: Detailed specification of output CSV formatsSPARK_ANALYSIS_README.md: Usage guide for analysis scriptsEXPERIMENTAL_HYPOTHESES.md: Mapping of experimental hypotheses to specific analysesPLOTTING_GUIDE.md: Complete guide to generating publication-quality plotsTAIL_LABELING.md: Methodology for identifying and labeling tail regions
analyze_experimental_hypotheses.py: Comprehensive analysis script for testing experimental claims- Calcium activity comparisons
- Wave directionality analysis
- Spatial matching
- Tail response analysis
- Condition comparisons (contact vs non-contact, etc.)
diagnose_tiffs.py: Diagnostic tool to inspect TIFF file propertiesconvert_tiffs_for_viewing.py: Convert 16-bit TIFFs to 8-bit for previewplot_poke_locations.py: Visualize all poke locations across processing runs
simulations/: Simulation framework for generating synthetic Ca²⁺ wave data- Generate data with configurable embryos, poke locations, and wave parameters
- Test hypotheses with controlled conditions
- Compare simulated vs real data patterns
- See
simulations/README.mdfor details
Generated during processing (not included in repo if large):
spark_tracks.csv: Per-frame Ca²⁺ event datavector_clusters.csv: Per-cluster summariesplots/: Visualization outputs
pip install opencv-python numpy tifffile pandas matplotlibpython wave-vector-tiff-parser.py /path/to/tiff/folder 100 \
--fps 10 \
--csv spark_tracks.csv \
--out-video output.mp4Arguments:
folder(positional): Folder of TIFF frames, or a single multi-page TIFFpoke_frame(positional): 0-based frame index where injury/poke occurs (t=0 reference)--fps: Frame rate (frames per second)--csv: Output CSV path (defaultspark_tracks.csv)--poke-x,--poke-y: Optional poke coordinates (if auto-detection fails)--out-video: Optional output video with overlays
python spark_tracks_to_clusters.py spark_tracks.csvpython visualize_spark_tracks.py spark_tracks.csv \
--clusters-csv vector_clusters.csv \
--output-dir plots/- 16-bit image support: Works directly with scientific imaging data
- Multi-page TIFF support: Handles time-lapse stacks efficiently
- Automatic embryo detection: Dynamic edge-based segmentation
- Anatomical coordinates: AP/DV position mapping relative to head-tail axis
- Spark tracking: Links detections across frames with gap-filling
- Memory efficient: Processes one frame at a time to handle large datasets
See wave-vector.md for complete documentation of CSV formats.
Per-frame measurements with columns:
track_id,frame_idx,time_sx,y: Position in pixelsvx,vy,speed,angle_deg: Velocity and directionarea: Spatial extentembryo_id: Which embryo (A/B)ap_norm,dv_px: Anatomical coordinatesdist_from_poke_px: Distance from injury site
Per-cluster summaries with columns:
cluster_id,n_frames,duration_sstart_x_px,end_x_px,net_displacement_px,path_length_pxmean_speed_px_per_s,peak_speed_px_per_smean_angle_deg,angle_dispersion_degtotal_area_px2_frames: Integrated signal "volume"
# 1. Process images (folder, poke frame 50, 15 fps)
python wave-vector-tiff-parser.py ~/data/embryos 50 --fps 15
# 2. Generate summaries
python spark_tracks_to_clusters.py spark_tracks.csv
# 3. Visualize
python visualize_spark_tracks.py spark_tracks.csv \
--clusters-csv vector_clusters.csv \
--output-dir analysis_plots/
# 4. Analyze results
# Use pandas, R, or your preferred analysis tool on the CSV filesA second pipeline scores the verbatim claims in Calcium claims.docx against the
imaging data and assembles a single combined report,
analysis_results/claims_all_in_one.pdf.
claims_doc_parser.py: Parses the claims table out ofCalcium claims.docx(one record per claim with layer / pattern / orientation / poke location).parse_xy_coordinates.py: Parses the manualXY coordinates.xlsxground-truth (all 39 sheets) into a tidyanalysis_results/xy_ground_truth.csv(prefix, video_stem, side, landmark, landmark_class, frame, x, y). This is the authoritative poke / head-tail geometry and organ-response layer.score_landmark_responses.py: For every manually-annotated organ landmark (cement gland / eye / tail / local), measures the robust-peak ΔF/F₀ in a disk at the annotated pixel straight from the C-channel TIFF — an automated corroboration of the human annotation (landmark_responses.csv+.png). Also tags each landmark stimulated/neighbor using the real poke side.wave_laterality_analysis.py: Scores neighbor-side waves and bidirectional spread per video. Whenxy_ground_truth.csvis present it splits the two embryos with the real poke + head/tail geometry (assigns each wave origin to the nearest annotated embryo segment; the poke side is the stimulated embryo) and falls back to the PCA estimate only for single-embryo videos.generate_claim_wave_overlays.py: Per claim, overlays the relevant-side wave-front vectors on the brightest microscopy frame of the relevant videos (montage PNG + animated GIF per claim group), embedded into the inventory PDF.generate_tested_claims_summary.py: Builds the one-page summary slide (claims_tested_summary.pdf) — every tested claim group with its live verdict and a thumbnail graph.generate_claims_inventory_pdf.py: Full inventory of all verbatim claims grouped by Layer, each tagged TESTED / TESTABLE NOW / PARTIAL / NOT YET with a live verdict (claims_inventory.pdf), plus laterality evidence pages.generate_claims_nomask_report.py: All-pixel side-region ΔF/F₀ traces and per-claim verdicts (claims_nomask_report.pdf).generate_claim_video_mapping_pdf.py: Which Box videos map to each claim (claim_video_mapping.pdf).merge_claims_all_in_one.py: Merges the summary slide + component PDFs intoclaims_all_in_one.pdf.
# 1. Build the wave catalog across all videos (dense vectors + roll-up)
python batch_wave_catalog.py --root "/path/to/Calcium videos"
# 1b. Parse the manual XY ground truth + score organ-response landmarks
python parse_xy_coordinates.py --xlsx "/path/to/XY coordinates.xlsx"
python score_landmark_responses.py
# 1c. Package a versioned Box deliverable (reports + tables + MANIFEST + sidecars)
python package_science_deliverables.py --include-gifs --include-detection-qa
# 2. Score laterality / bidirectionality (uses the real geometry if present)
python wave_laterality_analysis.py
# 2b. (optional) Render per-claim wave-vector overlays on the embryo frame
python generate_claim_wave_overlays.py
# 3. Build the summary slide, then the full claims inventory
python generate_tested_claims_summary.py
python generate_claims_inventory_pdf.py
# 3b. Export probabilistic KG (morphopkg/spc/1.0 TriG + JSON for Probknow)
python export_calcium_claims_to_pkg.py
# 4. (Re)generate the other component reports as needed, then merge
python merge_claims_all_in_one.pyThe merge prefers claims_tested_summary.pdf as the first page and skips any
component PDF that is missing.
Major pipeline scripts write a sidecar <output>.provenance.json next to each
primary artifact (git commit, Python + package versions, timestamps, inputs).
CSV outputs also get a # comment header with the same summary. A rolling
analysis_results/RUN_INDEX.jsonl logs every run. The combined PDF cover and
provenance page include the git commit; Box releases bundle all sidecars under
04_provenance/pipeline_sidecars/.
- The script automatically detects embryos from the first frames where they're visible
- Poke detection can be automatic (pink arrow overlay) or manual (--poke-x/--poke-y)
- Supports recursive subdirectory traversal for organized data
- Memory-efficient processing handles large time-lapse series