/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Config file for defining DSL2 per module options and publishing paths
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Available keys to override module options:
        ext.args   = Additional arguments appended to command in module.
        ext.args2  = Second set of arguments appended to command in module (multi-tool modules).
        ext.args3  = Third set of arguments appended to command in module (multi-tool modules).
        ext.prefix = File name prefix for output files.

    Per-group publish paths use
    06_per_group/{integration}/{subset}/{leiden|label}/...
----------------------------------------------------------------------------------------
*/

process {

    publishDir = [
        path: { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" },
        mode: params.publish_dir_mode,
        saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
    ]

    withName: '.*:LOAD_H5AD:ADATA_READRDS' {
        ext.prefix = { meta.id + '_converted_' + meta.type }
        publishDir = [
            path: { "${params.outdir}/01_load_h5ad" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: '.*:LOAD_H5AD:SCANPY_READH5' {
        ext.prefix = { meta.id + '_converted_' + meta.type }
        publishDir = [
            path: { "${params.outdir}/01_load_h5ad" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: '.*:LOAD_H5AD:ADATA_READCSV' {
        ext.prefix = { meta.id + '_converted_' + meta.type }
        publishDir = [
            path: { "${params.outdir}/01_load_h5ad" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    // Size extraction
    withName: COLLECT_SIZES {
        publishDir = [
            path: { "${params.outdir}/02_quality_control/sizes" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') || filename.endsWith('.json') ? null : filename },
        ]
    }

    // Empty droplet removal

    withName: '.*:EMPTY_DROPLET_REMOVAL:CELLBENDER_REMOVEBACKGROUND' {
        ext.prefix = { meta.id + '_cellbender' }
        ext.args   = {
            [
                "--epochs ${params.cellbender_epochs}",
                meta.expected_cells > 0 ? "--expected-cells ${meta.expected_cells}" : '',
            ].join(' ').trim()
        }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/empty_droplet_removal" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: '.*:EMPTY_DROPLET_REMOVAL:ANNDATA_BARCODES' {
        ext.prefix = { meta.id + '_subset' }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/empty_droplet_removal" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    // Quality control

    withName: QC_RAW {
        ext.prefix       = { meta.id + '_raw' }
        ext.section_name = 'Unfiltered QC plots'
        publishDir       = [
            path: { "${params.outdir}/02_quality_control/qc_raw" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') || filename.endsWith('.json') ? null : filename },
        ]
    }

    withName: QC_FILTERED {
        ext.prefix       = { meta.id + '_preprocessed' }
        ext.section_name = 'Filtered QC plots'
        publishDir       = [
            path: { "${params.outdir}/02_quality_control/qc_filtered" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') || filename.endsWith('.json') ? null : filename },
        ]
    }

    // Ambient RNA removal

    withName: CELDA_DECONTX {
        ext.prefix = { meta.id + '_decontx' }
        ext.batch_col = { meta.batch_col }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/ambient_rna_removal" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: '.*:AMBIENT_RNA_REMOVAL:CELLBENDER_REMOVEBACKGROUND' {
        ext.prefix = { meta.id + '_cellbender' }
        ext.args   = { "--epochs ${params.cellbender_epochs}" }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/ambient_rna_removal" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: '.*:AMBIENT_RNA_REMOVAL:CELLBENDER_MERGE' {
        ext.prefix       = { meta.id + '_cellbender' }
        publishDir       = [
            path: { "${params.outdir}/02_quality_control/ambient_rna_removal" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SOUPX {
        ext.prefix = { meta.id + '_soupX' }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/ambient_rna_removal" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    // Custom filtering

    withName: SCANPY_FILTER {
        ext.prefix = { meta.id + '_filtered' }
        ext.section_name = 'Filter threshold histograms'
        ext.description = 'QC metric histograms with applied filter thresholds'

        publishDir = [
            path: { "${params.outdir}/02_quality_control/custom_thresholds" },
            mode: params.publish_dir_mode,
            saveAs: { filename ->
                if (filename.equals('versions.yml') || filename.endsWith('.json')) {
                    null
                } else if (filename.endsWith('.png')) {
                    filename
                } else if (params.save_intermediates) {
                    filename
                } else {
                    null
                }
            },
        ]
    }

    // Doublet detection

    withName: SCVITOOLS_SOLO {
        ext.prefix = { meta.id + '_solo' }
        ext.batch_key = { meta.batch_col }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/doublet_detection/solo" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCANPY_SCRUBLET {
        ext.prefix = { meta.id + '_scrublet' }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/doublet_detection/scrublet" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: DOUBLETDETECTION {
        ext.prefix = { meta.id + '_doubletdetection' }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/doublet_detection/doubletdetection" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCDBLFINDER {
        ext.prefix = { meta.id + '_scdblfinder' }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/doublet_detection/scdblfinder" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: DOUBLETREMOVAL {
        publishDir = [
            path: { "${params.outdir}/02_quality_control/doublet_detection" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') || filename.endsWith('.json') ? null : filename },
        ]
    }

    withName: SCANPY_CELLCYCLE {
        ext.prefix = { meta.id + '_cellcycle' }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/cell_cycle" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: FINALIZE_QC_ANNDATAS {
        ext.prefix = { meta.id + '_qc' }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/finalized" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: QC_REPORT {
        container = 'docker.io/saditya88/qcreport:0.1.1'
        label = 'process_medium'
        ext.prefix = 'qc-report'
        publishDir = [
            path: { "${params.outdir}/10_reports" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: MYGENE {
        ext.prefix = { meta.id + '_mygene' }
        ext.input_col = { meta.geneid_col }
        ext.output_col = { 'symbols' }
        publishDir = [
            enabled: false
        ]
    }

    withName: SET_INDEX {
        ext.axis = 'var'
        ext.column = { meta.symbol_col }
        publishDir = [
            enabled: false
        ]
    }

    withName: HUGOUNIFIER_GET {
        publishDir = [
            path: { "${params.outdir}/02_quality_control/unify/hugounifier" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: HUGOUNIFIER_APPLY {
        ext.prefix = { meta.id + '_hugounifier' }
        publishDir = [
            path: { "${params.outdir}/02_quality_control/unify/hugounifier" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: ADATA_UNIFY {
        ext.prefix             = { meta.id + '_unified' }
        ext.symbol_col         = { meta.symbol_col }
        ext.geneid_col         = { meta.geneid_col }
        ext.counts_layer       = { meta.counts_layer }
        ext.duplicate_var_resolution = { params.duplicate_var_resolution }
        ext.batch_col                = { meta.batch_col }
        ext.label_col                = { meta.label_col }
        ext.unknown_label            = { meta.unknown_label }
        publishDir             = [
            path: { "${params.outdir}/02_quality_control/unify" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    // Merge datasets

    withName: ADATA_MERGE {
        publishDir = [
            path: { "${params.outdir}/03_combine/merge" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SUBSETVAR_INNER {
        ext.prefix = { meta.id + '_inner' }
        publishDir = [
            path: { "${params.outdir}/03_combine/subsetvar" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SUBSETVAR_INTEGRATE {
        ext.prefix = { meta.id + '_integrate_inner' }
        publishDir = [
            path: { "${params.outdir}/03_combine/subsetvar" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: ADATA_UPSETGENES {
        publishDir = [
            path: { "${params.outdir}/03_combine/merge" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') || filename.endsWith('.json') ? null : filename },
        ]
    }

    // Prepare integration

    withName: SCANPY_HVGS {
        ext.prefix = { meta.id + '_hvg' }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/input_hvg" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCRY_DEVIANCE {
        ext.prefix = { meta.id + '_deviance' }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/input_deviance" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: '.*:INTEGRATE:ADATA_TORDS' {
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/input_hvg" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    // Integration

    withName: SCVITOOLS_SCVI {
        ext.prefix                 = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        ext.n_hidden               = { params.scvi_n_hidden }
        ext.n_layers               = { params.scvi_n_layers }
        ext.n_latent               = { params.scvi_n_latent }
        ext.dispersion             = { params.scvi_dispersion }
        ext.gene_likelihood        = { params.scvi_gene_likelihood }
        ext.max_epochs             = { params.scvi_max_epochs }
        ext.categorical_covariates = { params.scvi_categorical_covariates }
        ext.continuous_covariates  = { params.scvi_continuous_covariates }
        ext.use_observed_lib_size  = { params.scvi_use_observed_lib_size }
        publishDir                 = [
            path: { "${params.outdir}/03_combine/integrate/scvi" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.endsWith("model.pt") || (params.save_intermediates && !filename.equals('versions.yml')) ? filename : null },
        ]
    }

    withName: SCVITOOLS_SCANVI {
        ext.prefix                 = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        ext.n_hidden               = { params.scvi_n_hidden }
        ext.n_layers               = { params.scvi_n_layers }
        ext.n_latent               = { params.scvi_n_latent }
        ext.dispersion             = { params.scvi_dispersion }
        ext.gene_likelihood        = { params.scvi_gene_likelihood }
        ext.max_epochs             = { params.scvi_max_epochs }
        ext.categorical_covariates = { params.scvi_categorical_covariates }
        ext.continuous_covariates  = { params.scvi_continuous_covariates }
        ext.use_observed_lib_size  = { params.scvi_use_observed_lib_size }
        publishDir                 = [
            path: { "${params.outdir}/03_combine/integrate/scanvi" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.endsWith("model.pt") || (params.save_intermediates && !filename.equals('versions.yml')) ? filename : null },
        ]
    }

    withName: SYMPHONY_HARMONYINTEGRATE {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/symphony" },
            mode: params.publish_dir_mode,
            saveAs: { filename ->
                if (filename.endsWith('_reference.h5ad')) {
                    return 'symphony_reference.h5ad'
                }
                if (params.save_intermediates && !filename.equals('versions.yml')) {
                    return filename
                }
                return null
            },
        ]
    }

    withName: SYMPHONY_MAPEMBEDDING {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/symphony" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCANPY_BBKNN {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/bbknn" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCANORAMA_INTEGRATE {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/scanorama" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SEURAT_INTEGRATION {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/seurat" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: '.*:INTEGRATE:ADATA_READRDS' {
        publishDir = [
            enabled: false
        ]
    }

    withName: SCANPY_COMBAT {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/combat" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCANPY_PCA {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') + '_pca' }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/pca" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCANPY_LOG1PNORM {
        ext.prefix = { meta.id + '_log1pnorm' }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/normalization" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCANPY_PEARSONRESIDUALS_HVGS {
        ext.prefix = { meta.id + '_pearson_residuals_hvgs' }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/input_pearson_residuals_hvgs" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCRAN_NORMALIZATION {
        ext.prefix = { meta.id + '_scran' }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/normalization" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCARCHES_EXPIMAP {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/expimap" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: '.*:SCIMILARITY:UNTAR' {
        publishDir = [
            enabled: false
        ]
    }

    withName: SCIMILARITY_EMBED {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/scimilarity" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCIMILARITY_ANNOTATE {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') + '_annotate' }
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/scimilarity" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: SCIBMETRICS_BENCHMARK {
        publishDir = [
            path: { "${params.outdir}/03_combine/integrate/scib_metrics" },
            mode: params.publish_dir_mode,
            saveAs: { filename ->
                filename.equals('versions.yml') || filename.endsWith('_mqc.json')
                    ? null
                    : filename
            },
        ]
    }

    withName: ADATA_MERGEEMBEDDINGS {
        ext.prefix = { (meta.integration ?: meta.id) + (meta.subset ? "-${meta.subset}" : '') }
        publishDir = [
            path: { "${params.outdir}/03_combine/merge_emb/${meta.integration ?: meta.id}" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    // Celltype assignment

    withName: CELLDEX_FETCHREFERENCE {
        publishDir = [
            enabled: false
        ]
    }

    withName: CELLTYPES_SINGLER {
        ext.prefix = { meta.id + '_singler' }
        publishDir = [
            path: { "${params.outdir}/04_celltypes/singler" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: CELLTYPES_CELLTYPIST {
        ext.prefix = { meta.id + '_celltypist' }
        publishDir = [
            path: { "${params.outdir}/04_celltypes/celltypist" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: CYTETYPE {
        ext.prefix = { meta.id + '_cytetype' }
        publishDir = [
            path: { "${params.outdir}/08_cytetype" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    // Clustering

    withName: NEIGHBORS {
        ext.prefix = { meta.id + '_neighbors' }
        publishDir = [
            path: { "${params.outdir}/05_cluster_dimred/${meta.integration}/neighbors" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: LEIDEN {
        ext.prefix = { meta.id + '_leiden' }
        publishDir = [
            path: { "${params.outdir}/05_cluster_dimred/${meta.integration}/leiden" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.endsWith(".png") || (params.save_intermediates && !filename.equals('versions.yml')) ? filename : null },
        ]
    }

    withName: ENTROPY {
        ext.prefix = { meta.id + '_entropy' }
        ext.plot_basis = 'umap'
        publishDir = [
            path: { "${params.outdir}/05_cluster_dimred/${meta.integration}/entropy" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.endsWith(".png") || (params.save_intermediates && !filename.equals('versions.yml')) ? filename : null },
        ]
    }

    withName: UMAP {
        ext.prefix = { meta.id + '_umap' }
        publishDir = [
            path: { "${params.outdir}/05_cluster_dimred/${meta.integration}/umap" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: TSNE {
        ext.prefix = { meta.id + '_tsne' }
        publishDir = [
            path: { "${params.outdir}/05_cluster_dimred/${meta.integration}/tsne" },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: ".*:PSEUDOBULKING:PSEUDOBULK" {
        ext.prefix = { meta.id + '_pseudobulk' }
        publishDir = [
            path: {
                def integration = meta.integration ?: 'merged'
                def subset = meta.subset ?: 'global'
                def grouping = meta.resolution != null ? "leiden/${meta.resolution}" : "${meta.obs_key ?: 'label'}"
                "${params.outdir}/06_per_group/${integration}/${subset}/${grouping}/differential_expression/pseudobulk/aggregation"
            },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: PYDESEQ2_DIFFERENTIAL {
        ext.prefix = { meta.id + '_pydeseq2' }
        publishDir = [
            path: {
                def integration = meta.integration ?: 'merged'
                def subset = meta.subset ?: 'global'
                def grouping = meta.resolution != null ? "leiden/${meta.resolution}" : "${meta.obs_key ?: 'label'}"
                "${params.outdir}/06_per_group/${integration}/${subset}/${grouping}/differential_expression/pseudobulk/pydeseq2"
            },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: EDGEPYTHON_DIFFERENTIAL {
        ext.prefix = { meta.id + '_edgepython' }
        publishDir = [
            path: {
                def integration = meta.integration ?: 'merged'
                def subset = meta.subset ?: 'global'
                def grouping = meta.resolution != null ? "leiden/${meta.resolution}" : "${meta.obs_key ?: 'label'}"
                "${params.outdir}/06_per_group/${integration}/${subset}/${grouping}/differential_expression/pseudobulk/edgepython"
            },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: EDGEPYTHON_SCDIFFERENTIAL {
        ext.prefix = { meta.id + "_${meta.celltype}_edgepython_sc" }
        publishDir = [
            path: {
                def integration = meta.integration ?: 'merged'
                def subset = meta.subset ?: 'global'
                def grouping = meta.resolution != null ? "leiden/${meta.resolution}" : "${meta.obs_key ?: 'label'}"
                "${params.outdir}/06_per_group/${integration}/${subset}/${grouping}/differential_expression/single_cell/edgepython"
            },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }
    withName: SCANPY_PAGA {
        ext.prefix = { meta.id + '_paga' }
        publishDir = [
            path: {
                def integration = meta.integration ?: 'merged'
                def subset = meta.subset ?: 'global'
                def grouping = meta.resolution != null ? "leiden/${meta.resolution}" : "${meta.obs_key ?: 'label'}"
                "${params.outdir}/06_per_group/${integration}/${subset}/${grouping}/paga"
            },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.endsWith(".png") || (params.save_intermediates && !filename.equals('versions.yml')) ? filename : null },
        ]
    }

    withName: LIANA_RANKAGGREGATE {
        ext.prefix = { meta.id + '_liana' }
        publishDir = [
            path: {
                def integration = meta.integration ?: 'merged'
                def subset = meta.subset ?: 'global'
                def grouping = meta.resolution != null ? "leiden/${meta.resolution}" : "${meta.obs_key ?: 'label'}"
                "${params.outdir}/06_per_group/${integration}/${subset}/${grouping}/liana"
            },
            mode: params.publish_dir_mode,
            saveAs: { filename ->
                filename.endsWith(".png") || (params.save_intermediates && !filename.equals('versions.yml') && !filename.endsWith('_mqc.json')) ? filename : null
            },
        ]
    }

    withName: LIANA_BYSAMPLE {
        ext.prefix = { meta.id + '_liana_bysample' }
        publishDir = [
            path: {
                def integration = meta.integration ?: 'merged'
                def subset = meta.subset ?: 'global'
                def grouping = meta.resolution != null ? "leiden/${meta.resolution}" : "${meta.obs_key ?: 'label'}"
                "${params.outdir}/06_per_group/${integration}/${subset}/${grouping}/liana/by_sample"
            },
            mode: params.publish_dir_mode,
            enabled: params.save_intermediates,
            saveAs: { filename -> params.save_intermediates && !filename.equals('versions.yml') ? filename : null },
        ]
    }

    withName: CELL2CELL_TENSOR {
        ext.prefix = { meta.id + '_cell2cell' }
        publishDir = [
            path: {
                def integration = meta.integration ?: 'merged'
                def subset = meta.subset ?: 'global'
                def grouping = meta.resolution != null ? "leiden/${meta.resolution}" : "${meta.obs_key ?: 'label'}"
                "${params.outdir}/06_per_group/${integration}/${subset}/${grouping}/cell2cell"
            },
            mode: params.publish_dir_mode,
            saveAs: { filename ->
                filename.endsWith(".png") || (params.save_intermediates && !filename.equals('versions.yml') && !filename.endsWith('_mqc.json')) ? filename : null
            },
        ]
    }

    withName: SCANPY_RANKGENESGROUPS {
        ext.prefix = { meta.id + '_characteristic_genes' }
        publishDir = [
            path: {
                def integration = meta.integration ?: 'merged'
                def subset = meta.subset ?: 'global'
                def grouping = meta.resolution != null ? "leiden/${meta.resolution}" : "${meta.obs_key ?: 'label'}"
                "${params.outdir}/06_per_group/${integration}/${subset}/${grouping}/differential_expression/scanpy/${meta.de_method}/${meta.comparison_scope}"
            },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.endsWith(".png") || filename.endsWith(".csv") || (params.save_intermediates && !filename.equals('versions.yml')) ? filename : null },
        ]
    }

    // Finalize

    withName: '.*:FINALIZE:ADATA_EXTEND' {
        publishDir = [
            path: { "${params.outdir}/09_finalized" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: '.*:FINALIZE:ADATA_TORDS' {
        errorStrategy = { task.exitStatus in ((130..145) + 104) ? 'retry' : 'ignore' }
        publishDir    = [
            path: { "${params.outdir}/09_finalized" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    withName: '.*:FINALIZE:ADATA_PREPCELLXGENE' {
        ext.prefix = { meta.id + '_cellxgene' }
        publishDir = [
            path: { "${params.outdir}/09_finalized" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }

    // MultiQC
    withName: MULTIQC {
        ext.args   = { params.multiqc_title ? "--title \"${params.multiqc_title}\"" : '' }
        publishDir = [
            path: { "${params.outdir}/11_multiqc" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
        ]
    }
}
