Lukas Heumos
05/07/2026, 12:32 PMNico Trummer
05/07/2026, 12:58 PMargs). Now for scanpy I tried to always do one module per function that I needed and the parameters to this function can be passed via args. But there are some annoying things with this:
1. Scanpy has two internal levels of hierarchy (pp/tl/etc and then the actual tool). nf-core only allows one level of hierarchy per tool, that's why it's scanpy/pca and not scanpy/tl/pca
2. Between nextflow modules, the only way to pass data is writing to disk. Scanpy/Rapids were designed to keep data in-memory between processing steps. So we end up with quite a bit of IO overhead
3. The only real alternative to having one module per function would be to have a scanpy module that has the exact function to be used as an input - e.g. something like SCANPY('tl', 'pca', args, adata) which could work in certain cases, but then if you need any wrapping logic that is specific to certain functions, it would soon become a nightmare. And for example #C077PUX8DBP has a lot of these, for example outputs that should be passed to multiqc.
So I think nextflow and scanpy/rapids will never be best friends, and I am annoyed by this too. Still I have not been able to come up with a better approach than creating one module per tool within scanpy, and I don't have any better ideas currently. But I'm very open to discuss, maybe we can find something betterLukas Heumos
05/07/2026, 1:11 PM/bin. This is also antipattern because ideally, there shouldn't be any such scripts. I'd argue they're a "nextflow code smell".
Performance wise, I do fear however that having such individual modules that always load & write is stupid. RSC is most efficient when you put the matrix to the GPU once (cupy) and you keep it there for all GPU computations. Every time you read & write, you have to move the matrix to the CPU (and back) which is expensive. I actually think this is an even bigger problem that we need to discuss.
Maybe we just need to work with local modules that act as supermodules for a whole set of steps for a pipeline? Maybe something generalizable aka a proper nf-core module is antipattern?Nico Trummer
05/07/2026, 1:27 PM/bin are not bundled with the module - e.g. if you do nf-core modules install scanpy/pca , the script in /bin won't be included. That's why we are currently mostly using the template syntax, which stores the python in the module directory. In future there will probably also be a slightly different approach (module-specific bin-directory), but that does not really have an effect on our discussion
So there are two sides concerning the performance thinking here:
1. Nextflow allows parallelization, e.g. running different doublet detection tools, integration methods, and similar things in parallel. Also it allows to process multiple datasets in parallel
2. Large modules allow using less IO operations, thus better performance for 'linear' workflows
Now the idea of official nf-core modules is to make them small, general building blocks that can be shared across different pipelines. With local modules, of course there is more flexibility. But then there is two extremes:
1. Having a single supermodule that basically is the entire pipeline (which makes it useless to have a nextflow pipeline in the first place)
2. Having one module per task, lots of IO, but following the general nf-core structure better and potentially more parallelization
Now the optimal solution will probably be somewhere in between. Something where one module contains what in nf-core rather would generally be considered a subworkflow. But defining the boundaries of these modules probably requires a lot of thinking beforehandLukas Heumos
05/07/2026, 1:30 PMNico Trummer
05/07/2026, 1:31 PMNico Trummer
05/07/2026, 1:31 PMLukas Heumos
05/07/2026, 1:31 PMGary Burnett
05/07/2026, 1:32 PMNico Trummer
05/07/2026, 1:33 PMMaybe what could be useful is a CLI tool that sits between nextflow and scanpy/rapids, provides the CLI to nextflow and internally runs an entire subworkflow.
Then, we could implement a shared nf-core module that encodes a single call to that intermediate CLI tool and fully comply with nf-core standards. It could also abstract the difference between rapids and scanpy away
Nico Trummer
05/07/2026, 1:36 PMMaybe there is a way to make rsc work as a subworkflow. That way we can keep everything in memory until after.The problem is that there is no way of sharing memory across modules - as there is no way of influencing even on which machine a certain task will be executed on. So there is no such thing as shared memory between modules in a subworkflow.
Gary Burnett
05/07/2026, 1:37 PMNico Trummer
05/07/2026, 1:47 PMscverse clusterumap file.h5ad --rapids . Then we could build a shared, atomic nf-core module that does all of the desired actions in-memory. And with the --rapids flag it could work with both scanpy or RSC as backendLukas Heumos
05/07/2026, 2:02 PMLet me know your thoughts on this, it's currently the thing that sounds most feasible for me
> Maybe what could be useful is a CLI tool that sits between nextflow and scanpy/rapids, provides the CLI to nextflow and internally runs an entire subworkflow.
> Then, we could implement a shared nf-core module that encodes a single call to that intermediate CLI tool and fully comply with nf-core standards. It could also abstract the difference between rapids and scanpy awayhttps://github.com/nictru/scanpy-cli in a way? I guess that's why you partially implemented it at some point. It wouldn't be the nicest interface but it would probably work.
Lukas Heumos
05/07/2026, 2:03 PMNico Trummer
05/07/2026, 2:04 PMLukas Heumos
05/07/2026, 2:04 PMNico Trummer
05/07/2026, 2:04 PMGiven that we're talking about like 3 pipelines here at the moment, I am somewhat tempted to just implement local modules that do just what we want them to doThat's probably the most pragmatic way
Lukas Heumos
05/07/2026, 2:10 PMNico Trummer
05/07/2026, 2:10 PMLukas Heumos
05/07/2026, 2:11 PMLukas Heumos
05/07/2026, 2:11 PMNico Trummer
05/07/2026, 2:16 PMI wonder whether we should ping some nextflow devs to make them aware of this design issue? Maybe it's something for the future roadmap. Sharing resources between stepsI can't imagine this to be possible, because it would require having shared memory between different containers (and this does not mean just docker, but any supported containerization engine) and also one would need to be able to influence how tasks are assigned to machines (and if I understood AWS batch correctly, a new instance is launched for every task). Also the resuming might be weird. Well I see a lot of obstacles here and I think nextflow was just not made for this, but I am not a nextflow dev. Having their opinion would sure be interesting. Maybe @Ben Sherman
Lukas Heumos
05/07/2026, 2:20 PMBen Sherman
05/07/2026, 11:59 PMnextflow module run
Nextflow module registry also makes nf-core modules just one namespace among many. So you could share these modules via a different namespace if they are worth sharing but don't fit nf-core requirements