Constantin Ahlmann-Eltze's Avatar

Constantin Ahlmann-Eltze

@const-ae.bsky.social

Postdoc at UCL with James Reading. Previously at EMBL working with Wolfgang Huber. Biostats, R, cancer immunology

1,926 Followers  |  537 Following  |  56 Posts  |  Joined: 28.08.2023  |  1.8838

Latest posts by const-ae.bsky.social on Bluesky

I wrote about AI foundation models for biology last year: www.nytimes.com/2024/03/10/s... Benchmarking tests since then aren't finding that they're better than simpler models of how genes and cells work.

04.08.2025 16:45 β€” πŸ‘ 27    πŸ” 13    πŸ’¬ 0    πŸ“Œ 0
Preview
Deep-learning-based gene perturbation effect prediction does not yet outperform simple linear baselines - Nature Methods The analysis presented in this Brief Communication shows that, despite their complexity, current deep learning models do not outperform linear baselines in predicting gene perturbation effects, thus e...

An analysis shows that current deep learning models do not beat linear baselines in predicting gene perturbation effects, thus emphasizing the importance of further method development and evaluation. @const-ae.bsky.social @wkhuber.bsky.social @s-anders.bsky.social

www.nature.com/articles/s41...

04.08.2025 16:07 β€” πŸ‘ 44    πŸ” 19    πŸ’¬ 0    πŸ“Œ 3

Haha, would also be a succinct summary of most of my academic work πŸ˜…

04.08.2025 15:38 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Preview
Deep-learning-based gene perturbation effect prediction does not yet outperform simple linear baselines Nature Methods - The analysis presented in this Brief Communication shows that, despite their complexity, current deep learning models do not outperform linear baselines in predicting gene...

And lastly, a big shout-out to @wkhuber.bsky.social and @s-anders.bsky.social!

Link to pdf: rdcu.be/ey7x0

04.08.2025 13:52 β€” πŸ‘ 5    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

- Li et al. doi.org/10.1101/2024.12.23.630036
- Chen Li et al. doi.org/10.1101/2024.12.20.629581
- Wong et al. doi.org/10.1093/bioinformatics/btaf317

And probably many more that I am missing here.

04.08.2025 13:52 β€” πŸ‘ 8    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

- @kasparmartens.bsky.social et al. openreview.net/forum?id=eb3ndUlkt4
- Gaudelet et al. doi.org/10.48550/arXiv.2404.16907
- @aaronwtr.bsky.social et al. openreview.net/forum?id=t04D9bkKUq
- Bendidi et al. doi.org/10.48550/arXiv.2410.13956
- Wu et al. doi.org/10.48550/arXiv.2408.10609

04.08.2025 13:52 β€” πŸ‘ 8    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

I also encourage everyone to checkout the parallel efforts by groups around the world who came to similar conclusions:
- @ekernf01.bsky.social et al. doi.org/10.1101/2023.07.28.551039
- Csendes et al. doi.org/10.1186/s12864-025-11600-2
- @kasia.codes et al. doi.org/10.1186/s13059-025-03574-x

04.08.2025 13:52 β€” πŸ‘ 11    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
A recap of virtual cell releases circa June 2025 In October 2024, I twote that β€œsomething is deeply wrong” with what we now call virtual cell models. A lot has happened since then: modelers are advancing new architectures and mining new sources of i...

*We benchmarked scGPT, scFoundation, GEARS, CPA (which claim predictive ability), and scBERT, Geneformer, and UCE (which do not claim this ability). I can't comment on methods released in the last 5 months. For a summary of recent developments, see @ekernf01.bsky.social's post

04.08.2025 13:52 β€” πŸ‘ 7    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Beeswarm plot of the prediction error across different methods of double perturbations showing that all methods (scGPT, scFoundation, UCE, scBERT, Geneformer, GEARS, and CPA) perform worse than the additive baseline.

Beeswarm plot of the prediction error across different methods of double perturbations showing that all methods (scGPT, scFoundation, UCE, scBERT, Geneformer, GEARS, and CPA) perform worse than the additive baseline.

Line plot of the true positive rate against the false discovery proportion showing that none of the methods is better at finding non additive interactions than simply predicting no change.

Line plot of the true positive rate against the false discovery proportion showing that none of the methods is better at finding non additive interactions than simply predicting no change.

Our paper benchmarking foundation models for perturbation effect prediction is finally published πŸŽ‰πŸ₯³πŸŽ‰

www.nature.com/articles/s41...

We show that none of the available* models outperform simple linear baselines. Since the original preprint, we added more methods, metrics, and prettier figures!

🧡

04.08.2025 13:52 β€” πŸ‘ 85    πŸ” 36    πŸ’¬ 2    πŸ“Œ 6
A recap of virtual cell releases circa June 2025 In October 2024, I twote that β€œsomething is deeply wrong” with what we now call virtual cell models. A lot has happened since then: modelers are advancing new architectures and mining new sources of i...

In October 2024, I twote that "something is deeply wrong" with what we now call virtual cell models. A lot has happened since then. How am I updating? New blog post: ekernf01.github.io/virtual-cell...

27.07.2025 23:48 β€” πŸ‘ 11    πŸ” 1    πŸ’¬ 1    πŸ“Œ 0

That's amazing. Congratulations πŸŽ‰

03.07.2025 08:23 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Preview
Tracing colorectal malignancy transformation from cell to tissue scale The transformation of normal intestinal epithelium into colorectal cancer (CRC) involves coordinated changes across molecular, cellular, and architectural scales; yet, how these layers integrate remai...

Going from methods dev to full on cancer bio has been tough. All the more excited to see this out at lastβ€”

www.biorxiv.org/content/10.1...

@pascual-reguant.bsky.social
@brukerspatial.bsky.social
@hoheyn.bsky.social

27.06.2025 18:33 β€” πŸ‘ 12    πŸ” 5    πŸ’¬ 1    πŸ“Œ 0
With {tidylog}, you see friendly messages like:
summarise: now 3 rows and 3 columns, ungrouped
filter: removed 2 rows (67%), one row remaining

With {tidylog}, you see friendly messages like: summarise: now 3 rows and 3 columns, ungrouped filter: removed 2 rows (67%), one row remaining

With {tidylog}, you see friendly messages like:

summarise: now 3 rows and 3 columns, ungrouped

filter: removed 2 rows (67%), one row remaining

✨ It’s like having a gentle co-pilot, helping you track what each step is doing β€” super useful for debugging and learning!

08.05.2025 13:28 β€” πŸ‘ 23    πŸ” 8    πŸ’¬ 2    πŸ“Œ 0
Spatialproteomics orchestrates workflows to analyze highly multiplexed images. It segments cells, processes images, quantifies proteins, predicts cell types, and provides neighborhood analysis methods, all while integrating into the scverse ecosystem.

Spatialproteomics orchestrates workflows to analyze highly multiplexed images. It segments cells, processes images, quantifies proteins, predicts cell types, and provides neighborhood analysis methods, all while integrating into the scverse ecosystem.

New preprint out!

We introduce 𝐬𝐩𝐚𝐭𝐒𝐚π₯𝐩𝐫𝐨𝐭𝐞𝐨𝐦𝐒𝐜𝐬, a Python package for end-to-end processing and analysis of highly multiplexed immunofluorescence imaging data.

Built on xarray and dask, with seamless integration into the scverse ecosystem.
www.biorxiv.org/content/10.1...

05.05.2025 11:30 β€” πŸ‘ 11    πŸ” 1    πŸ’¬ 1    πŸ“Œ 0

(2/3)

Constantin Ahlmann-Eltze showcased impressive work on assembling an atlas of T cells in precancerous samples. They developed the R packages treelabel and Shinytreelabel, which showed GITR+ Tregs are enriched in several precancerous samples, suggesting avenues for future treatments

10.04.2025 11:43 β€” πŸ‘ 2    πŸ” 1    πŸ’¬ 0    πŸ“Œ 0

A friend of mine recommends the Bahnstadt Edeka Fleischtheke. (Vegetarian myself, so no first-hand experience πŸ˜…)

21.03.2025 07:29 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Preview
Analysis of multi-condition single-cell data with latent embedding multivariate regression Nature Genetics - Latent embedding multivariate regression models multi-condition single-cell RNA-seq using a continuous latent space, enabling data integration, per-cell gene expression prediction...

🦎 Differential expression analysis relies on cluster identities, unless you perform a regression along continuous representation in latent space. LEMUR from @const-ae.bsky.social & @wkhuber.bsky.social does that neatly for scRNA-seq data!
πŸ”— doi.org/10.1038/s415... πŸ§ͺ @naturegenet.bsky.social

19.03.2025 07:44 β€” πŸ‘ 13    πŸ” 3    πŸ’¬ 0    πŸ“Œ 1
Open positions - AG Imkeller

We are recruiting a PhD student in Computational Biology to work on omics data and spatial integration in cellular immunotherapy of cancer. Joint project with the group of Florian BΓΌttner. @loewe-fci.bsky.social
agimkeller.github.io/recruit.html

11.03.2025 08:59 β€” πŸ‘ 4    πŸ” 6    πŸ’¬ 0    πŸ“Œ 1
Preview
LEMUR simplified | const-ae A simplified implementation of the LEMUR algorithm.

Blog post by @const-ae.bsky.social with a simple explanation of the manifold regression algorithm & code that underlies our paper β€œAnalysis of multi-condition single-cell data with latent embedding multivariate regression” (doi.org/10.1002/eji....).

const-ae.name/post/2025-01...

04.03.2025 18:27 β€” πŸ‘ 26    πŸ” 5    πŸ’¬ 1    πŸ“Œ 0
Post image

Abstract submissions are now open for the European Bioconductor Conference (EuroBioC2025), 17-19 September 2025 in Barcelona.
This event will bring together the Bioconductor community in Europe to advance bioinformatics, data science, and open-source software.

eurobioc2025.bioconductor.org

28.02.2025 15:07 β€” πŸ‘ 9    πŸ” 6    πŸ’¬ 0    πŸ“Œ 0
wrap_in_tibble <- function(...){
  dots <- rlang::enquos(...)
  # Let's assume I can be sure that the environment is the same across dots
  eval_in_mtcars(tibble::tibble(!!! dots), env = rlang::quo_get_env(dots[[1]]))
}

eval_in_mtcars <- function(expr, env){
  quo <- rlang::enquo(expr)
  quo <- rlang::new_quosure(rlang::quo_squash(quo), env)
  rlang::eval_tidy(quo, data = mtcars[1:3,])
}

wrap_in_tibble(mpg * 3)
#> # A tibble: 3 Γ— 1
#>   `mpg * 3`
#>       <dbl>
#> 1      63  
#> 2      63  
#> 3      68.4

wrap_in_tibble <- function(...){ dots <- rlang::enquos(...) # Let's assume I can be sure that the environment is the same across dots eval_in_mtcars(tibble::tibble(!!! dots), env = rlang::quo_get_env(dots[[1]])) } eval_in_mtcars <- function(expr, env){ quo <- rlang::enquo(expr) quo <- rlang::new_quosure(rlang::quo_squash(quo), env) rlang::eval_tidy(quo, data = mtcars[1:3,]) } wrap_in_tibble(mpg * 3) #> # A tibble: 3 Γ— 1 #> `mpg * 3` #> <dbl> #> 1 63 #> 2 63 #> 3 68.4

I have found a solution that works by squashing the quasi-quotation and explicitly setting the environment.

I still wonder if there is a better solution or if someone (maybe @lionelhenry.bsky.social? πŸ˜…) would have to write a `quo_squash` function that retains the environments. :)

#Rstats

19.02.2025 15:57 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

You are right; that would work here. I am still a bit uneasy because, even after re-reading the evaluation chapter in Advanced R, I feel like I don't understand the bigger picture.

19.02.2025 14:11 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
  wrap_in_tibble2 <- function(...){
    dots <- rlang::enexprs(...)
    eval_in_mtcars(tibble::tibble(!!! dots))
  }
  fnc <- function(){
    a <- 700
    wrap_in_tibble2(mpg * a, cyl + 3)
  }
  a <- 0
  fnc()
  wrap_in_tibble2(mpg * a, cyl + 3)

wrap_in_tibble2 <- function(...){ dots <- rlang::enexprs(...) eval_in_mtcars(tibble::tibble(!!! dots)) } fnc <- function(){ a <- 700 wrap_in_tibble2(mpg * a, cyl + 3) } a <- 0 fnc() wrap_in_tibble2(mpg * a, cyl + 3)

In this example `enexprs()` would work, but it breaks if I call `wrap_in_tibble` from a function. (When calling fnc(), it should evaluate the quasi-quotation with a=700.)

19.02.2025 09:41 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
wrap_in_df <- function(...){
  dots <- rlang::enquos(...)
  eval_in_mtcars(data.frame(!!! dots))
}
wrap_in_tibble <- function(...){
  dots <- rlang::enquos(...)
  eval_in_mtcars(tibble::tibble(!!! dots))
}
eval_in_mtcars <- function(expr){
  quo <- rlang::enquo(expr)
  rlang::eval_tidy(quo, data = mtcars[1:3,])
}

wrap_in_df(mpg * 2, cyl + 3)
#>   X.mpg...2 X.cyl...3
#> 1      42.0         9
#> 2      42.0         9
#> 3      45.6         7
wrap_in_tibble(mpg * 2, cyl + 3)
#> Error: object 'mpg' not found

wrap_in_df <- function(...){ dots <- rlang::enquos(...) eval_in_mtcars(data.frame(!!! dots)) } wrap_in_tibble <- function(...){ dots <- rlang::enquos(...) eval_in_mtcars(tibble::tibble(!!! dots)) } eval_in_mtcars <- function(expr){ quo <- rlang::enquo(expr) rlang::eval_tidy(quo, data = mtcars[1:3,]) } wrap_in_df(mpg * 2, cyl + 3) #> X.mpg...2 X.cyl...3 #> 1 42.0 9 #> 2 42.0 9 #> 3 45.6 7 wrap_in_tibble(mpg * 2, cyl + 3) #> Error: object 'mpg' not found

Is there some clever syntax to control when a quasi-quotation is evaluated so that the wrap_in_tibble function works? 🧐

(Context in stackoverflow.com/questions/79...)

#Rstats #rlang

19.02.2025 09:17 β€” πŸ‘ 2    πŸ” 2    πŸ’¬ 3    πŸ“Œ 0
Video thumbnail

Thrilled to share that our work from Trumpp Lab @hi-stem @dkfz.bsky.social is out in Nature.
We provide the first single-cell data on neurons infiltrating pancreatic tumors, offering new insights into cancer therapy. #cancerneuroscience @cn-hd.bsky.social
www.nature.com/articles/s41...

18.02.2025 09:37 β€” πŸ‘ 49    πŸ” 20    πŸ’¬ 2    πŸ“Œ 3

Thanks. It's actually build on top of plotgardener, so thanks for that one :)

12.02.2025 11:55 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Plot produced with exactplot

Plot produced with exactplot

xp_compose_plots(
  xp_text("Welcome to \\texttt{exactplot} with \\LaTeX{} support", x = 1, y = 2, 
          fontsize = xp$fontsize_large, fontface = "bold"),
  xp_text("A) Flipper length vs.\\ beak size", x = 1, y = 8),
  xp_plot(scatter_plot, x = 0, y = 12, width = 80, height = 40),
  
  xp_text("B) Beak sizes", x = 84, y = 8),
  xp_plot(beak_lengths, x = 82, y = 12, width = 58, height = 40),
  xp_text(density_formula, x = 99, y = 12, fontsize = xp$fontsize_small),
  
  width = 140, height = 52,
  keep_tex_file = FALSE, filename = "example.pdf"
)

xp_compose_plots( xp_text("Welcome to \\texttt{exactplot} with \\LaTeX{} support", x = 1, y = 2, fontsize = xp$fontsize_large, fontface = "bold"), xp_text("A) Flipper length vs.\\ beak size", x = 1, y = 8), xp_plot(scatter_plot, x = 0, y = 12, width = 80, height = 40), xp_text("B) Beak sizes", x = 84, y = 8), xp_plot(beak_lengths, x = 82, y = 12, width = 58, height = 40), xp_text(density_formula, x = 99, y = 12, fontsize = xp$fontsize_small), width = 140, height = 52, keep_tex_file = FALSE, filename = "example.pdf" )

I just uploaded the first version of {{exactplot}} to github.com/const-ae/exa... πŸŽ‰

It produces figures with consistent font size, Latex labels, and millimeter-perfect layouting. It's an alternative to patchwork with less elegant syntax but much more flexibility.

#rstats

12.02.2025 11:40 β€” πŸ‘ 103    πŸ” 24    πŸ’¬ 6    πŸ“Œ 0
Plot produced with exactplot that contains Latex labels and has embedded fonts.

Plot produced with exactplot that contains Latex labels and has embedded fonts.

I compiled my workflow for producing pretty figures into a small package: github.com/const-ae/exa...

My trick is to use `tikzDevice` and do all the rendering with Luatex. I can position every panel and label with millimeter precision and still modify the output with Illustrator.

12.02.2025 11:27 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
Preview
Pseudobulk with proper offsets has the same statistical properties as generalized linear mixed models in single-cell case-control studies AbstractMotivation. Generalized linear mixed models (GLMMs), such as the negative-binomial or Poisson linear mixed model, are widely applied to single-cell

@epigenci.bsky.social makes a pretty convincing case for pseudobulk (as opposed to GLMMs) in multi-sample single cell studies here: doi.org/10.1093/bioi... . #bioinformatics

31.01.2025 22:55 β€” πŸ‘ 10    πŸ” 2    πŸ’¬ 0    πŸ“Œ 1

We have additional available spots. Please consider joining! It will be a blast.

30.01.2025 16:24 β€” πŸ‘ 2    πŸ” 2    πŸ’¬ 0    πŸ“Œ 0

@const-ae is following 20 prominent accounts