Projects

A small sample of things I've worked on recently. As with all specialized solutions, these approaches have caveats; feel free to reach out to talk more!

LLM agents scRNA-seq FastAPI React Jupyter

Organism: natural-language analysis of RNA-sequencing data

Biological data is being generated faster than bioinformatics capacity can keep up with it, and most of the scientists asking the questions do not write code. Organism lets bench scientists explore single-cell and bulk RNA-seq data by asking questions in plain English. Every answer is backed by real code that runs in a live Jupyter kernel, so the figures, tables, and methods are inspectable, reproducible, and reusable rather than a black box.

Approach

A React frontend talks to a FastAPI backend that streams each analysis turn to the browser. The scientific work goes through a shared tool layer: typed contracts around scanpy, pyDESeq2, gseapy, and related libraries that the model calls, with execution happening in a per-session kernel so state carries across questions. QC, normalization, clustering, differential expression, and gene set enrichment are first-class tools rather than free-form code generation, which keeps results scientifically defensible and diagnosable when they go wrong.

The hosted version runs on Modal with a warm spare kernel to cut pre-question latency, mirrors the full session record (code, plots, dataset cards) to Supabase after every turn, and ships with a curated shelf of public atlases whose published analyses are reused instead of recomputed. I co-build Organism with a collaborator and own a large share of the backend, tool layer, and hosting work.

Status

Organism is live as a hosted demo with Google sign-in. Bring an AnnData file or pick a curated atlas, ask a question, and follow the thread wherever the biology takes it.


Bayesian optimization Genomic variant analysis Machine learning

Maximizing accuracy of genomic somatic short variant calling through hyperparameter optimization

Most tools developed for genomic variant calling in scRNA-seq were built for 3' or 5' based droplet-based sequencing, often using pseudobulk approaches to account for the large number of cells with low coverage. I used a binary classifier to benchmark and optimize accuracy of single nucleotide variant calling in long read scRNA-seq.

Approach

Using patient-matched WGS and 150 bp paired-end SMARTseq of tumors, I ran the GATK best practices workflow to produce to VCF files. After extensive germline variant filtering, traditional grid search was used to find a good set of HaplotypeCaller parameters. TPESampler was then run to find the VCF attributes that maximized the F1 score of mutation matching (balance of precision and recall). Finally, a grid search was repeat using optimized hyperparameters to arrive at a final set of HaplotypeCaller parameters.

Results

At its core, this project is about eliminating noise and technical sequencing error in variant calling for long read RNA-seq. My findings reveal that after filtering of variants based on variant PHRED score (13, as associated with an alpha of 5%) and HaplotypeCaller's FILT flags, min depth becomes the most consequential hyperparameter for optimizing calling specificity. This suggests that the main challenge in somatic variant calling in scRNA-seq is germline variant leakage.


Polynomial regression NGS Data cleaning sklearn

A mathematical and data-driven QC threshold selection for scRNA-seq datasets

Another seldom scrutinized cookie-cutter practice in bioinformatics is the universal acceptance of arbitrary quality control thresholds in scRNA-seq preprocessing. These thresholds are on metrics that vary immensely based on platform, sequencer, dataset, etc. I implemented a quantitative approach to identify and filter low-quality cells from a given scRNA-seq dataset.

Approach

Cells in the dataset can be thought of as a combination of two populations: healthy, well sequenced cells being the first and low quality cells, stressed cells, and debris being the second. In this schematic, the distribution of the quality metrics is a combination of two zero-bounded curves: the first (healthy) being Gaussian-like and the contaminant distribution resembling a reverse J-shape curve, with a its peak near zero.

Cells are first binned based on their number of uniquely mapping reads. (For droplet based datasets, this would be replaced with UMI count, which is unavailable for SMARTseq). Savitzky-Gola was applied for smoothing of the histogram to reduce noise while preserving peak structure. The inflection point at which the second derivative crosses zero was set as the quality threshold.

Results

The optimal minimum uniquely mapping reads threshold was calculated to be 55,490, which is markedly higher than the common arbitrary threshold of 1,000 reads. This threshold is inherently dataset-dependent, preventing inappropriate data filtering due to 'industry standards'.