#
# @include "_run_fbpca_stage.mro"
#

#
# Copyright (c) 2020 10X Genomics, Inc. All rights reserved.
#

filetype h5;
filetype pickle;
#
# @include "_sc_rna_analyzer_stages.mro"
#

#
# Copyright (c) 2019 10X Genomics, Inc. All rights reserved.
#

filetype csv;
filetype h5;
filetype html;
filetype json;
filetype pickle;
filetype binary;
#
# @include "_cr_lib_stages.mro"
#

#
# Copyright (c) 2020 10X Genomics, Inc. All rights reserved.
#
# WARNING: This file is auto-generated.
# DO NOT MODIFY THIS FILE DIRECTLY
#

filetype ann.bincode.lz4;
filetype arp.bincode;
filetype asf;
filetype bam;
filetype bam.bai;
filetype bcc.bincode;
filetype bcm.bincode;
filetype bed;
filetype bin;
filetype bincode;
filetype bincode.lz4;
filetype blf.json;
filetype bmsf;
filetype bsf.bincode;
filetype bui;
filetype csf;
filetype csv;
filetype em.json;
filetype fa;
filetype fasta;
filetype fasta.fai;
filetype fastq;
filetype fastq.lz4;
filetype fbc.bincode;
filetype frf.bincode;
filetype h5;
filetype html;
filetype json;
filetype msm.bincode;
filetype pb;
filetype rpc;
filetype shard;
filetype tbcc.bincode;
filetype tsv;
filetype txt;
filetype umi;
filetype vloupe;
#
# @include "_basic_sc_rna_counter_stages.mro"
#

#
# Copyright (c) 2019 10X Genomics, Inc. All rights reserved.
#

filetype bam;
filetype bam.bai;
filetype csv;
filetype fastq;
filetype json;
filetype h5;
filetype pickle;
filetype bincode;
#
# @include "_common_stages.mro"
#

#
# Copyright (c) 2017 10X Genomics, Inc. All rights reserved.
#

filetype bam;
filetype bam.bai;
filetype csv;
filetype fastq;
filetype json;
filetype pickle;
filetype fa;
#
# @include "_spatial_reporting_stages.mro"
#

#
# Copyright (c) 2019 10X Genomics, Inc. All rights reserved.
#

filetype csv;
filetype json;
filetype h5;
filetype html;
filetype png;
filetype jpg;
filetype txt;
#
# @include "_sc_rna_targeted_analyzer_stages.mro"
#

#
# Copyright (c) 2018 10X Genomics, Inc. All rights reserved.
#

filetype csv;
filetype pdf;
filetype h5;
filetype json;
filetype bam;
filetype bam.bai;
filetype fa;
#
# @include "_targeted_analyzer.mro"
#

filetype csv;
filetype h5;
filetype json;
#
# @include "_common_cloupe_stages.mro"
#

#
# Copyright (c) 2016 10X Genomics, Inc. All rights reserved.
#

filetype cloupe;
filetype csv;
filetype json;
filetype h5;
filetype txt;
#
# @include "_spatial_cloupe_stages.mro"
#

#
# Copyright (c) 2019 10X Genomics, Inc. All rights reserved.
#

filetype csv;
filetype json;
#
# @include "_spatial_imaging_stages.mro"
#

#
# Copyright (c) 2019 10X Genomics, Inc. All rights reserved.
#

filetype jpg;
filetype png;
filetype txt;
filetype json;
filetype html;
filetype h5;
filetype csv;
filetype gpr;
#
# @include "_spatial_imaging_cs.mro"
#

filetype jpg;
filetype png;
filetype tiff;
filetype txt;
filetype json;
#
# @include "_spatial_preflights.mro"
#

#
# Copyright (c) 2020 10X Genomics, Inc. All rights reserved.
#
filetype gpr;

#
# @include "_cr_lib_stages.mro"
#

struct SampleBamFile(
    string  sample,
    bam     bam_file,
    bam.bai bam_index_file,
)

struct VdjRefFastaFolder(
    fa regions,
    fa donor_regions,
)

struct VdjRefFolder(
    VdjRefFastaFolder fasta,
    json              reference,
)

struct DetectChemistryStageOutputs(
    string chemistry_type,
    bool   is_antibody_only,
)

struct GemWellVdjChemistry(
    string chemistry_type,
    string chain_type,
    string receptor,
)

struct BarcodeCompatibilityStageOutputs(
    string[] libraries_to_translate,
)

struct GemWellDetectChemistry(
    map[]                            sample_defs_count,
    DetectChemistryStageOutputs      detect_count_chem,
    GemWellVdjChemistry[]            detect_vdj_chem,
    BarcodeCompatibilityStageOutputs check_barcodes_compatibility,
)

struct GemWellFiles(
    int[]             gem_groups,
    asf[]             alignments,
    map[]             read_chunks,
    bui[]             bc_umi_info,
    bmsf[]            per_barcode_metrics_shard,
    fastq[]           read1s,
    ann.bincode.lz4[] annotation_files,
    string            target_set_name,
    path              bam_header,
    frf.bincode       slfe_feature_reference,
    string            barcode_whitelist,
)

struct FileOrBytes(
    file   file,
    string bytes,
)

struct CommonInputs(
    string sample_id,
    string sample_desc,
    string multi_config_sha,
)

struct CellCalling(
    int      recovered_cells,
    int      force_cells,
    json     cell_barcodes,
    string   override_mode,
    string[] override_library_types,
)

struct CountInputs(
    map[]       sample_def,
    string      chemistry,
    map         custom_chemistry_def,
    path        reference_path,
    json        gene_index,
    map[]       primers,
    CellCalling cell_calling_config,
    float       subsample_rate,
    int         initial_reads,
    int         primer_initial_reads,
    string[]    special_genomic_regions,
    int         r1_length,
    int         r2_length,
    int         trim_polya_min_score,
    int         trim_tso_min_score,
    bool        no_secondary_analysis,
    bool        no_target_umi_filter,
    file        feature_reference,
    bool        include_introns,
    string      aligner,
    map         genetic_demux_params,
    bool        enforce_library_concordance,
    bool        no_bam,
)

struct VdjInputs(
    map[]    sample_def,
    string   chemistry,
    map      custom_chemistry_def,
    map[]    primers,
    int      force_cells,
    float    subsample_rate,
    int      initial_reads,
    int      primer_initial_reads,
    string[] special_genomic_regions,
    bool     denovo,
    int      r1_length,
    int      r2_length,
    path     ground_truth_clonotype_path,
    path     inner_enrichment_primers,
    string   chain_type,
)

struct VdjGenInputs(
    path reference_path,
    path vdj_reference_path,
)

struct BasicPipelineConfig(
    bool disable_count,
    bool disable_vdj,
)

struct VdjAggrCsvLibrary(
    string library_id,
    path   vdj_contig_info,
    string donor,
    string origin,
    map    meta,
)

struct VdjAggrInput(
    VdjAggrCsvLibrary[] libraries,
)

struct VdjAggrResults(
    csv    clonotypes,
    fa     donor_ref_fa,
    fasta  consensus_fasta,
    csv    filtered_contig_annotations_csv,
    csv    consensus_annotations_csv,
    html   web_summary,
    vloupe vloupe,
)

#
# @include "_basic_sc_rna_counter_stages.mro"
#

struct CellCalling(
    int      recovered_cells,
    int      force_cells,
    json     cell_barcodes,
    string   override_mode,
    string[] override_library_types,
)

#
# @include "_run_fbpca_stage.mro"
#

stage RUN_FBPCA(
    in  h5     matrix_h5,
    in  map[]  library_info,
    in  int    num_pcs,
    in  bool   skip,
    in  bool   is_antibody_only,
    out pickle dimred_matrix,
    out pickle matrix_barcode_feature_info,
    src py     "../rna/stages/analyzer/run_fbpca",
) split (
)

#
# @include "_sc_rna_analyzer_stages.mro"
#

stage ANALYZER_PREFLIGHT(
    in  bool   skip,
    in  h5     filtered_matrices_h5,
    in  csv    use_genes,
    in  csv    exclude_genes,
    in  csv    use_bcs,
    in  int    num_analysis_bcs,
    in  int    force_cells,
    in  int    random_seed,
    in  int    num_pca_bcs,
    in  int    num_pca_genes,
    in  int    num_principal_comps,
    in  int    cbc_knn,
    in  float  cbc_alpha,
    in  float  cbc_sigma,
    in  bool   cbc_realign_panorama,
    in  int    max_clusters,
    in  int    graphclust_neighbors,
    in  float  neighbor_a,
    in  float  neighbor_b,
    in  int    tsne_perplexity,
    in  int    tsne_input_pcs,
    in  int    tsne_max_dims,
    in  int    tsne_max_iter,
    in  int    tsne_stop_lying_iter,
    in  int    tsne_mom_switch_iter,
    in  float  tsne_theta,
    in  int    umap_n_neighbors,
    in  int    umap_input_pcs,
    in  int    umap_max_dims,
    in  float  umap_min_dist,
    in  string umap_metric,
    out bool   skip,
    out bool   is_antibody_only,
    src py     "../rna/stages/analyzer/analyzer_preflight",
) using (
    volatile = strict,
)

stage REANALYZER_PREFLIGHT(
    in  h5 filtered_matrices_h5,
    src py "../rna/stages/analyzer/reanalyzer_preflight",
) using (
    volatile = strict,
)

stage PREPROCESS_MATRIX(
    in  h5   matrix_h5,
    in  bool skip,
    in  int  random_seed,
    in  csv  use_genes,
    in  csv  exclude_genes,
    in  csv  use_bcs,
    in  int  num_bcs,
    in  int  force_cells,
    in  bool is_antibody_only,
    out h5   cloupe_matrix_h5,
    out h5   preprocessed_matrix_h5,
    out bool is_multi_genome,
    src py   "../rna/stages/analyzer/preprocess_matrix",
) split (
) using (
    volatile = strict,
)

stage RUN_MULTIGENOME_ANALYSIS(
    in  h5   filtered_matrices_h5,
    in  bool is_multi_genome,
    in  bool skip,
    out path multi_genome_csv,
    out path multi_genome_json,
    out json multi_genome_summary,
    src py   "../rna/stages/analyzer/run_multigenome_analysis",
) split (
) using (
    volatile = strict,
)

stage RUN_PCA(
    in  h5   matrix_h5,
    in  bool skip,
    in  int  random_seed,
    in  int  num_bcs,
    in  int  num_genes,
    in  int  num_pcs,
    in  bool is_antibody_only,
    out h5   pca_h5,
    out path pca_csv,
    src py   "../rna/stages/analyzer/run_pca",
) split (
) using (
    volatile = strict,
)

stage RUN_KMEANS(
    in  h5   matrix_h5,
    in  h5   pca_h5,
    in  bool skip,
    in  int  random_seed,
    in  int  max_clusters,
    in  int  num_bcs,
    in  int  num_pcs,
    out h5   kmeans_h5,
    out path kmeans_csv,
    src py   "../rna/stages/analyzer/run_kmeans",
) split (
    in  int  n_clusters,
) using (
    volatile = strict,
)

stage RUN_GRAPH_CLUSTERING(
    in  h5     matrix_h5,
    in  h5     pca_h5,
    in  int    num_neighbors       "Use this many neighbors",
    in  float  neighbor_a          "Use larger of (a+b*log10(n_cells) neighbors or num_neighbors",
    in  float  neighbor_b          "Use larger of (a+b*log10(n_cells) neighbors or num_neighbors",
    in  int    num_bcs             "Use this many cell-barcodes in clustering",
    in  int    input_pcs           "Use top N PCs",
    in  int    balltree_leaf_size,
    in  string similarity_type     "Type of similarity to use (nn or snn)",
    in  bool   skip,
    out h5     chunked_neighbors,
    out h5     clusters_h5,
    out path   clusters_csv,
    src py     "../rna/stages/analyzer/run_graph_clustering",
) split (
    in  pickle neighbor_index,
    in  h5     submatrix,
    in  int    row_start,
    in  int    total_rows,
    in  int    k_nearest,
    in  h5     use_bcs,
) using (
    volatile = strict,
)

stage MERGE_CLUSTERS(
    in  h5   matrix_h5,
    in  h5   pca_h5,
    in  h5   clusters_h5,
    in  bool skip,
    out h5   clusters_h5,
    out path clusters_csv,
    src py   "../rna/stages/analyzer/merge_clusters",
) split (
) using (
    volatile = strict,
)

stage COMBINE_CLUSTERING(
    in  bool skip,
    in  h5   kmeans_h5,
    in  path kmeans_csv,
    in  h5   graphclust_h5,
    in  path graphclust_csv,
    out h5   clustering_h5,
    out path clustering_csv,
    src py   "../rna/stages/analyzer/combine_clustering",
) using (
    volatile = strict,
)

stage RUN_DIFFERENTIAL_EXPRESSION(
    in  h5     matrix_h5,
    in  h5     clustering_h5,
    in  bool   skip,
    in  int    random_seed,
    in  int    max_clusters,
    in  bool   is_antibody_only,
    out h5     diffexp_h5,
    out path   diffexp_csv,
    src py     "../rna/stages/analyzer/run_differential_expression",
) split (
    in  string clustering_key,
) using (
    volatile = strict,
)

stage RUN_TSNE(
    in  h5     matrix_h5,
    in  h5     pca_h5,
    in  bool   skip,
    in  int    random_seed,
    in  int    perplexity,
    in  int    input_pcs,
    in  int    max_dims,
    in  int    max_iter,
    in  int    stop_lying_iter,
    in  int    mom_switch_iter,
    in  float  theta,
    in  bool   is_antibody_only,
    out h5     tsne_h5,
    out path   tsne_csv,
    src py     "../rna/stages/analyzer/run_tsne",
) split (
    in  int    tsne_dims,
    in  string feature_type,
) using (
    volatile = strict,
)

stage RUN_UMAP(
    in  h5     matrix_h5,
    in  h5     pca_h5,
    in  bool   skip,
    in  int    random_seed,
    in  int    n_neighbors,
    in  int    input_pcs,
    in  int    max_dims,
    in  float  min_dist,
    in  string metric,
    in  bool   is_antibody_only,
    out h5     umap_h5,
    out path   umap_csv,
    src py     "../rna/stages/analyzer/run_umap",
) split (
    in  int    umap_dims,
    in  string feature_type,
) using (
    volatile = strict,
)

stage SUMMARIZE_ANALYSIS(
    in  h5    matrix_h5,
    in  h5    pca_h5,
    in  h5    clustering_h5,
    in  h5    diffexp_h5,
    in  h5    tsne_h5,
    in  h5    umap_h5,
    in  path  pca_csv,
    in  path  clustering_csv,
    in  path  diffexp_csv,
    in  path  tsne_csv,
    in  path  umap_csv,
    in  json  multi_genome_summary,
    in  path  multi_genome_csv,
    in  path  multi_genome_json,
    in  bool  is_multi_genome,
    in  bool  chemistry_batch_correction,
    in  float batch_score_before_correction,
    in  float batch_score_after_correction,
    in  bool  skip,
    out path  analysis,
    out path  analysis_csv,
    out json  summary,
    src py    "../rna/stages/analyzer/summarize_analysis",
) split (
) using (
    volatile = strict,
)

stage PARSE_PARAM_CSV(
    in  csv    params_csv,
    out csv    params_csv,
    out int    num_analysis_bcs,
    out int    random_seed,
    out int    num_pca_bcs,
    out int    num_pca_genes,
    out int    num_principal_comps,
    out int    cbc_knn,
    out float  cbc_alpha,
    out float  cbc_sigma,
    out bool   cbc_realign_panorama,
    out int    max_clusters,
    out int    graphclust_neighbors,
    out float  neighbor_a,
    out float  neighbor_b,
    out int    tsne_perplexity,
    out int    tsne_input_pcs,
    out int    tsne_max_dims,
    out int    tsne_max_iter,
    out int    tsne_stop_lying_iter,
    out int    tsne_mom_switch_iter,
    out float  tsne_theta,
    out int    umap_n_neighbors,
    out int    umap_input_pcs,
    out int    umap_max_dims,
    out float  umap_min_dist,
    out string umap_metric,
    src py     "../rna/stages/analyzer/parse_csv",
) using (
    volatile = strict,
)

stage SUMMARIZE_REANALYSIS(
    in  string sample_id,
    in  string sample_desc,
    in  h5     filtered_matrices,
    in  path   analysis,
    in  json   analyze_matrices_summary,
    out html   web_summary,
    out json   summary,
    out path   feature_bc_matrix_mex,
    src py     "../rna/stages/analyzer/summarize_reanalysis",
) split (
) using (
    volatile = strict,
) retain (
    summary,
)

stage CORRECT_CHEMISTRY_BATCH(
    in  pickle dimred_matrix,
    in  pickle matrix_barcode_feature_info,
    in  map[]  library_info,
    in  int    cbc_knn,
    in  float  cbc_alpha,
    in  float  cbc_sigma,
    in  bool   cbc_realign_panorama,
    in  bool   skip,
    out float  batch_score_before_correction,
    out float  batch_score_after_correction,
    out h5     aligned_pca_h5,
    out path   aligned_pca_csv,
    src py     "../rna/stages/analyzer/correct_chemistry_batch",
) split (
    in  int    batch_id,
    in  map    batch_to_bc_indices,
    in  pickle ordered_dimred_matrix,
    in  pickle idx_to_batch_id,
    in  bool   need_reorder_barcode,
    in  pickle barcode_reorder_index,
    out binary batch_nearest_neighbor,
) using (
    mem_gb = 4,
)

stage CHOOSE_DIMENSION_REDUCTION(
    in  bool chemistry_batch_correction,
    out bool disable_run_pca,
    out bool disable_correct_chemistry_batch,
    src py   "../rna/stages/analyzer/choose_dimension_reduction",
)

stage CHOOSE_DIMENSION_REDUCTION_OUTPUT(
    in  bool   skip,
    in  h5[]   pca_h5_list,
    in  path[] pca_csv_list,
    out h5     pca_h5,
    out path   pca_csv,
    src py     "../rna/stages/analyzer/choose_dimension_reduction_output",
)

#
# @include "sc_rna_analyzer.mro"
#

pipeline SC_RNA_ANALYZER(
    in  h5     filtered_matrices_h5,
    in  map[]  aggr_library_info,
    in  bool   no_secondary_analysis,
    in  csv    use_genes,
    in  csv    exclude_genes,
    in  csv    use_bcs,
    in  int    num_analysis_bcs,
    in  int    random_seed,
    in  int    num_pca_bcs,
    in  int    num_pca_genes,
    in  int    num_principal_comps,
    in  bool   chemistry_batch_correction,
    in  int    cbc_knn,
    in  float  cbc_alpha,
    in  float  cbc_sigma,
    in  bool   cbc_realign_panorama,
    in  int    max_clusters,
    in  int    graphclust_neighbors,
    in  float  neighbor_a,
    in  float  neighbor_b,
    in  int    tsne_perplexity,
    in  int    tsne_input_pcs,
    in  int    tsne_max_dims,
    in  int    tsne_max_iter,
    in  int    tsne_stop_lying_iter,
    in  int    tsne_mom_switch_iter,
    in  float  tsne_theta,
    in  int    umap_n_neighbors,
    in  int    umap_input_pcs,
    in  int    umap_max_dims,
    in  float  umap_min_dist,
    in  string umap_metric,
    in  int    force_cells,
    in  bool   skip_multigenome_analysis,
    out path   analysis,
    out path   analysis_csv,
    out h5     cloupe_matrix_h5,
    out json   summary,
)
{
    call ANALYZER_PREFLIGHT(
        skip                 = self.no_secondary_analysis,
        filtered_matrices_h5 = self.filtered_matrices_h5,
        use_genes            = self.use_genes,
        exclude_genes        = self.exclude_genes,
        use_bcs              = self.use_bcs,
        num_analysis_bcs     = self.num_analysis_bcs,
        force_cells          = self.force_cells,
        random_seed          = self.random_seed,
        num_pca_bcs          = self.num_pca_bcs,
        num_pca_genes        = self.num_pca_genes,
        num_principal_comps  = self.num_principal_comps,
        cbc_knn              = self.cbc_knn,
        cbc_alpha            = self.cbc_alpha,
        cbc_sigma            = self.cbc_sigma,
        cbc_realign_panorama = self.cbc_realign_panorama,
        max_clusters         = self.max_clusters,
        graphclust_neighbors = self.graphclust_neighbors,
        neighbor_a           = self.neighbor_a,
        neighbor_b           = self.neighbor_b,
        tsne_perplexity      = self.tsne_perplexity,
        tsne_input_pcs       = self.tsne_input_pcs,
        tsne_max_dims        = self.tsne_max_dims,
        tsne_max_iter        = self.tsne_max_iter,
        tsne_stop_lying_iter = self.tsne_stop_lying_iter,
        tsne_mom_switch_iter = self.tsne_mom_switch_iter,
        tsne_theta           = self.tsne_theta,
        umap_n_neighbors     = self.umap_n_neighbors,
        umap_input_pcs       = self.umap_input_pcs,
        umap_max_dims        = self.umap_max_dims,
        umap_min_dist        = self.umap_min_dist,
        umap_metric          = self.umap_metric,
    ) using (
        volatile = true,
    )

    call PREPROCESS_MATRIX(
        matrix_h5        = self.filtered_matrices_h5,
        random_seed      = self.random_seed,
        use_genes        = self.use_genes,
        exclude_genes    = self.exclude_genes,
        use_bcs          = self.use_bcs,
        num_bcs          = self.num_analysis_bcs,
        force_cells      = self.force_cells,
        is_antibody_only = ANALYZER_PREFLIGHT.is_antibody_only,
        skip             = ANALYZER_PREFLIGHT.skip,
    ) using (
        volatile = true,
    )

    call RUN_MULTIGENOME_ANALYSIS(
        filtered_matrices_h5 = self.filtered_matrices_h5,
        is_multi_genome      = PREPROCESS_MATRIX.is_multi_genome,
        skip                 = ANALYZER_PREFLIGHT.skip,
    ) using (
        disabled = self.skip_multigenome_analysis,
        volatile = true,
    )

    call CHOOSE_DIMENSION_REDUCTION(
        chemistry_batch_correction = self.chemistry_batch_correction,
    ) using (
        local = true,
    )

    call RUN_PCA(
        matrix_h5        = PREPROCESS_MATRIX.preprocessed_matrix_h5,
        random_seed      = self.random_seed,
        num_bcs          = self.num_pca_bcs,
        num_genes        = self.num_pca_genes,
        num_pcs          = self.num_principal_comps,
        is_antibody_only = ANALYZER_PREFLIGHT.is_antibody_only,
        skip             = ANALYZER_PREFLIGHT.skip,
    ) using (
        disabled = CHOOSE_DIMENSION_REDUCTION.disable_run_pca,
        volatile = true,
    )

    call RUN_FBPCA(
        matrix_h5        = PREPROCESS_MATRIX.preprocessed_matrix_h5,
        library_info     = self.aggr_library_info,
        num_pcs          = self.num_principal_comps,
        skip             = ANALYZER_PREFLIGHT.skip,
        is_antibody_only = ANALYZER_PREFLIGHT.is_antibody_only,
    ) using (
        disabled = CHOOSE_DIMENSION_REDUCTION.disable_correct_chemistry_batch,
        volatile = true,
    )

    call CORRECT_CHEMISTRY_BATCH(
        dimred_matrix               = RUN_FBPCA.dimred_matrix,
        matrix_barcode_feature_info = RUN_FBPCA.matrix_barcode_feature_info,
        library_info                = self.aggr_library_info,
        cbc_knn                     = self.cbc_knn,
        cbc_alpha                   = self.cbc_alpha,
        cbc_sigma                   = self.cbc_sigma,
        cbc_realign_panorama        = self.cbc_realign_panorama,
        skip                        = ANALYZER_PREFLIGHT.skip,
    ) using (
        disabled = CHOOSE_DIMENSION_REDUCTION.disable_correct_chemistry_batch,
        volatile = true,
    )

    call CHOOSE_DIMENSION_REDUCTION_OUTPUT(
        skip         = ANALYZER_PREFLIGHT.skip,
        pca_h5_list  = [
            RUN_PCA.pca_h5,
            CORRECT_CHEMISTRY_BATCH.aligned_pca_h5,
        ],
        pca_csv_list = [
            RUN_PCA.pca_csv,
            CORRECT_CHEMISTRY_BATCH.aligned_pca_csv,
        ],
    )

    call RUN_KMEANS(
        matrix_h5    = PREPROCESS_MATRIX.preprocessed_matrix_h5,
        pca_h5       = CHOOSE_DIMENSION_REDUCTION_OUTPUT.pca_h5,
        random_seed  = self.random_seed,
        max_clusters = self.max_clusters,
        skip         = ANALYZER_PREFLIGHT.skip,
        num_bcs      = null,
        num_pcs      = null,
    ) using (
        volatile = true,
    )

    call RUN_GRAPH_CLUSTERING(
        matrix_h5          = PREPROCESS_MATRIX.preprocessed_matrix_h5,
        pca_h5             = CHOOSE_DIMENSION_REDUCTION_OUTPUT.pca_h5,
        num_neighbors      = self.graphclust_neighbors,
        neighbor_a         = self.neighbor_a,
        neighbor_b         = self.neighbor_b,
        input_pcs          = null,
        num_bcs            = null,
        similarity_type    = "nn",
        balltree_leaf_size = null,
        skip               = ANALYZER_PREFLIGHT.skip,
    ) using (
        volatile = true,
    )

    call MERGE_CLUSTERS(
        matrix_h5   = PREPROCESS_MATRIX.preprocessed_matrix_h5,
        pca_h5      = CHOOSE_DIMENSION_REDUCTION_OUTPUT.pca_h5,
        clusters_h5 = RUN_GRAPH_CLUSTERING.clusters_h5,
        skip        = ANALYZER_PREFLIGHT.skip,
    ) using (
        volatile = true,
    )

    call COMBINE_CLUSTERING(
        kmeans_h5      = RUN_KMEANS.kmeans_h5,
        kmeans_csv     = RUN_KMEANS.kmeans_csv,
        graphclust_h5  = MERGE_CLUSTERS.clusters_h5,
        graphclust_csv = MERGE_CLUSTERS.clusters_csv,
        skip           = ANALYZER_PREFLIGHT.skip,
    ) using (
        volatile = true,
    )

    call RUN_DIFFERENTIAL_EXPRESSION(
        matrix_h5        = PREPROCESS_MATRIX.preprocessed_matrix_h5,
        clustering_h5    = COMBINE_CLUSTERING.clustering_h5,
        random_seed      = self.random_seed,
        max_clusters     = self.max_clusters,
        is_antibody_only = ANALYZER_PREFLIGHT.is_antibody_only,
        skip             = ANALYZER_PREFLIGHT.skip,
    ) using (
        volatile = true,
    )

    call RUN_TSNE(
        matrix_h5        = PREPROCESS_MATRIX.preprocessed_matrix_h5,
        pca_h5           = CHOOSE_DIMENSION_REDUCTION_OUTPUT.pca_h5,
        random_seed      = self.random_seed,
        perplexity       = self.tsne_perplexity,
        input_pcs        = self.tsne_input_pcs,
        max_dims         = self.tsne_max_dims,
        max_iter         = self.tsne_max_iter,
        stop_lying_iter  = self.tsne_stop_lying_iter,
        mom_switch_iter  = self.tsne_mom_switch_iter,
        theta            = self.tsne_theta,
        is_antibody_only = ANALYZER_PREFLIGHT.is_antibody_only,
        skip             = ANALYZER_PREFLIGHT.skip,
    ) using (
        volatile = true,
    )

    call RUN_UMAP(
        matrix_h5        = PREPROCESS_MATRIX.preprocessed_matrix_h5,
        pca_h5           = CHOOSE_DIMENSION_REDUCTION_OUTPUT.pca_h5,
        random_seed      = self.random_seed,
        n_neighbors      = self.umap_n_neighbors,
        input_pcs        = self.umap_input_pcs,
        max_dims         = self.umap_max_dims,
        min_dist         = self.umap_min_dist,
        metric           = self.umap_metric,
        is_antibody_only = ANALYZER_PREFLIGHT.is_antibody_only,
        skip             = ANALYZER_PREFLIGHT.skip,
    ) using (
        volatile = true,
    )

    call SUMMARIZE_ANALYSIS(
        matrix_h5                     = PREPROCESS_MATRIX.preprocessed_matrix_h5,
        pca_h5                        = CHOOSE_DIMENSION_REDUCTION_OUTPUT.pca_h5,
        clustering_h5                 = COMBINE_CLUSTERING.clustering_h5,
        diffexp_h5                    = RUN_DIFFERENTIAL_EXPRESSION.diffexp_h5,
        tsne_h5                       = RUN_TSNE.tsne_h5,
        umap_h5                       = RUN_UMAP.umap_h5,
        pca_csv                       = CHOOSE_DIMENSION_REDUCTION_OUTPUT.pca_csv,
        clustering_csv                = COMBINE_CLUSTERING.clustering_csv,
        diffexp_csv                   = RUN_DIFFERENTIAL_EXPRESSION.diffexp_csv,
        tsne_csv                      = RUN_TSNE.tsne_csv,
        umap_csv                      = RUN_UMAP.umap_csv,
        multi_genome_summary          = RUN_MULTIGENOME_ANALYSIS.multi_genome_summary,
        multi_genome_csv              = RUN_MULTIGENOME_ANALYSIS.multi_genome_csv,
        multi_genome_json             = RUN_MULTIGENOME_ANALYSIS.multi_genome_json,
        is_multi_genome               = PREPROCESS_MATRIX.is_multi_genome,
        chemistry_batch_correction    = self.chemistry_batch_correction,
        batch_score_before_correction = CORRECT_CHEMISTRY_BATCH.batch_score_before_correction,
        batch_score_after_correction  = CORRECT_CHEMISTRY_BATCH.batch_score_after_correction,
        skip                          = ANALYZER_PREFLIGHT.skip,
    )

    return (
        analysis         = SUMMARIZE_ANALYSIS.analysis,
        analysis_csv     = SUMMARIZE_ANALYSIS.analysis_csv,
        cloupe_matrix_h5 = PREPROCESS_MATRIX.cloupe_matrix_h5,
        summary          = SUMMARIZE_ANALYSIS.summary,
    )
}

#
# @include "_cr_lib_stages.mro"
#

stage ALIGN_AND_COUNT(
    in  int               gem_well,
    in  map[]             read_chunks,
    in  path              reference_path,
    in  shard[]           valid_reads,
    in  shard[]           corrected_reads,
    in  shard[]           invalid_reads,
    in  fbc.bincode       feature_counts,
    in  frf.bincode       feature_reference,
    in  csv               target_set,
    in  map               chemistry_def,
    in  string            aligner,
    in  float             aligner_subsample_rate,
    in  bool              include_introns,
    in  bool              is_pd,
    in  int               targeted_umi_min_read_count,
    in  int               transcriptome_min_score,
    in  int               trim_polya_min_score,
    in  int               trim_tso_min_score,
    in  tbcc.bincode      total_barcode_counts,
    in  blf.json          barcode_subset,
    out csf[]             counts_bc_order,
    out csf[]             counts_feature_order,
    out bui[]             bc_umi_info,
    out asf[]             pos_sorted,
    out path              bam_header,
    out csv               barcode_summary,
    out ann.bincode.lz4[] annotation_files,
    out bmsf[]            per_barcode_metrics,
    src comp              "cr_lib martian align_and_count",
) split (
    in  map               range,
    out csf               counts_bc_order_shard,
    out csf               counts_feature_order_shard,
    out bui               bc_umi_info_shard,
    out asf               pos_sorted_shard,
    out bsf.bincode       barcode_summary_shard,
    out ann.bincode.lz4[] read_ann_files,
    out bmsf              metrics_shard,
) using (
    mem_gb   = 4,
    volatile = strict,
)

stage WRITE_POS_BAM(
    in  path            bam_header,
    in  asf[]           alignments,
    in  map[]           read_chunks,
    in  string          target_set_name,
    in  map             barcode_to_sample,
    out SampleBamFile   pos_sorted_bam,
    out SampleBamFile[] multi_pos_sorted_bam,
    src comp            "cr_lib martian write_pos_bam",
) split (
    in  map             range,
    in  bool            write_header,
    out map             sample_pos_sorted_bam_chunks,
) using (
    volatile = strict,
)

stage BARCODE_CORRECTION(
    in  int          gem_well,
    in  shard[]      invalid_uncorrected,
    in  string       barcode_whitelist,
    in  bcc.bincode  barcode_counts,
    in  bcm.bincode  valid_read_metrics,
    in  string[]     libraries_to_translate,
    out shard[]      valid_corrected,
    out shard[]      invalid,
    out json         summary,
    out bcc.bincode  corrected_barcode_counts,
    out tbcc.bincode total_barcode_counts,
    src comp         "cr_lib martian barcode_correction",
) split (
    in  map          range,
    out shard        valid_shard,
    out shard        invalid_shard,
    out bcm.bincode  chunk_summary,
) using (
    mem_gb   = 4,
    threads  = 4,
    volatile = strict,
)

stage WRITE_BARCODE_SUMMARY(
    in  int[]       unique_gem_groups,
    in  bui[]       bc_umi_info,
    in  frf.bincode feature_reference,
    in  string      barcode_whitelist,
    out h5          barcode_summary,
    src comp        "cr_lib martian write_barcode_summary",
) using (
    mem_gb   = 8,
    threads  = 1,
    volatile = strict,
)

stage COLLATE_METRICS(
    in  bmsf[]      per_barcode_metrics,
    in  path        reference_path,
    in  frf.bincode feature_reference,
    out json        summary,
    out csv         per_barcode_metrics,
    src comp        "cr_lib martian collate_metrics",
) using (
    mem_gb   = 1,
    volatile = strict,
)

stage WRITE_H5_MATRIX(
    in  int         gem_well,
    in  csf[]       counts,
    in  bcc.bincode bcs,
    in  string      barcode_whitelist,
    in  frf.bincode feature_reference,
    in  map         chemistry_def,
    in  string      sample_id,
    out h5          matrix,
    src comp        "cr_lib martian write_h5_matrix",
) using (
    mem_gb   = 2,
    threads  = 1,
    volatile = strict,
)

stage WRITE_MATRIX_MARKET(
    in  int         gem_well,
    in  csf[]       counts,
    in  bcc.bincode bcs,
    in  string      barcode_whitelist,
    in  frf.bincode feature_reference,
    out path        feature_bc_matrix,
    src comp        "cr_lib martian write_matrix_market",
) using (
    mem_gb   = 2,
    threads  = 1,
    volatile = strict,
)

stage COPY_VDJ_REFERENCE(
    in  path         vdj_reference_path,
    in  fa           vdj_t_donor_ref_fa,
    in  fa           vdj_b_donor_ref_fa,
    out VdjRefFolder vdj_reference,
    src comp         "cr_lib martian copy_vdj_reference",
)

stage DETECT_CHEMISTRY(
    in  map[]    sample_def,
    in  path     reference_path,
    in  string   chemistry_name_spec,
    in  string[] allowed_chems,
    in  int      r1_length,
    in  int      r2_length,
    out string   chemistry_type,
    out bool     is_antibody_only,
    src comp     "cr_lib martian detect_chemistry",
) using (
    mem_gb   = 20,
    volatile = strict,
)

stage COMBINE_GEM_WELL_CHEMISTRIES(
    in  GemWellDetectChemistry[] gem_well_detect_chemistry,
    out map                      library_to_chemistry,
    out string[]                 libraries_to_translate,
    out bool                     is_antibody_only,
    out GemWellDetectChemistry   legacy,
    src comp                     "cr_lib martian combine_gem_well_chemistries",
)

stage CHECK_BARCODES_COMPATIBILITY_VDJ(
    in  string vdj_chemistry_name,
    in  map[]  vdj_sample_def,
    in  string gex_chemistry_name,
    in  map[]  gex_sample_def,
    in  map    gex_custom_chemistry_def,
    in  map    vdj_custom_chemistry_def,
    in  bool   enforce_library_concordance,
    out float  similarity_score,
    src comp   "cr_lib martian vdj_gex_bc_compat",
)

stage CHECK_BARCODES_COMPATIBILITY(
    in  string   chemistry_name,
    in  map      custom_chemistry_def,
    in  map[]    sample_def,
    in  bool     enforce_library_concordance,
    out string[] libraries_to_translate,
    src comp     "cr_lib martian barcode_compatibility",
)

stage DETECT_VDJ_RECEPTOR(
    in  string force_receptor,
    in  path   vdj_reference_path,
    in  string chemistry,
    in  map[]  sample_def,
    out string receptor,
    src comp   "cr_lib martian detect_vdj_receptor",
) using (
    mem_gb   = 1,
    volatile = strict,
)

stage MAKE_SHARD(
    in  map         chemistry_def,
    in  int         gem_well,
    in  map[]       read_chunks,
    in  string      barcode_whitelist,
    in  int         r1_length,
    in  int         r2_length,
    in  float       subsample_rate,
    in  int         initial_read_pairs,
    in  path        reference_path,
    in  csv         feature_reference_path,
    in  csv         target_features,
    in  string      target_set_name,
    in  string[]    libraries_to_translate,
    out shard[]     valid,
    out shard[]     invalid,
    out bcc.bincode barcode_counts,
    out fbc.bincode feature_counts,
    out json        summary,
    out int         total_read_pairs,
    out bool        paired_end,
    out fastq[]     read1s,
    out frf.bincode feature_reference,
    out bcm.bincode bc_correct_summary,
    src comp        "cr_lib martian make_shard",
) split (
    in  int         chunk_id,
    in  frf.bincode feature_reference,
    out shard       valid_shard,
    out shard       invalid_shard,
    out rpc         read_prefix_counts,
    out umi         umi_counts,
    out msm.bincode chunk_summary,
    out fastq       read1_fastq,
) using (
    mem_gb   = 4,
    threads  = 4,
    volatile = strict,
)

stage MERGE_GEM_WELL_FILES(
    in  GemWellFiles[] unmerged_gem_well_files,
    out GemWellFiles   merged_gem_well_files,
    src comp           "cr_lib martian merge_gem_well_files",
) using (
    volatile = strict,
)

stage MERGE_METRICS(
    in  json[] summaries,
    out json   summary,
    src comp   "cr_lib martian merge_metrics",
) using (
    volatile = strict,
)

stage MULTI_PREFLIGHT(
    in  FileOrBytes config,
    src comp        "cr_lib martian multi_preflight",
) using (
    mem_gb   = 1,
    threads  = 1,
    volatile = strict,
)

stage PARSE_MULTI_CONFIG(
    in  string              sample_id,
    in  string              sample_desc,
    in  FileOrBytes         config,
    in  string              config_hash,
    in  map                 params,
    out CommonInputs        common_input,
    out CountInputs         count_input,
    out VdjInputs[]         vdj_inputs,
    out VdjGenInputs        vdj_gen_inputs,
    out BasicPipelineConfig basic_config,
    out csv                 config_file,
    src comp                "cr_lib martian parse_multi_config",
) using (
    mem_gb   = 6,
    threads  = 1,
    volatile = strict,
)

stage RUST_BRIDGE(
    in  int           gem_well,
    in  shard[]       valid_uncorrected,
    in  shard[]       valid_corrected,
    in  bcc.bincode   raw_barcode_counts,
    in  bcc.bincode   corrected_barcode_counts,
    in  bool          paired_end,
    out fastq.lz4[]   read1s,
    out bincode.lz4[] bc_sorted_rna_reads,
    out fastq.lz4[]   read2s,
    out int[]         gem_groups,
    out json[]        barcodes,
    out json          raw_barcode_counts_json,
    out json          corrected_barcode_counts_json,
    out int           n50_n50_rpu,
    out int           processed_read_pairs,
    src comp          "cr_lib martian rust_bridge",
) split (
    in  map           range,
    in  shard[]       valid_shards,
    out fastq.lz4     read1_shard,
    out bincode.lz4   chunk_bc_sorted_rna_reads,
    out fastq.lz4     read2_shard,
    out json          barcodes_shard,
    out bincode       n50s_shard,
) using (
    mem_gb = 4,
)

stage SET_ALIGNER_SUBSAMPLE_RATE(
    in  json        barcodes_under_tissue,
    in  bcc.bincode corrected_barcode_counts,
    in  int         rps_limit,
    out float       aligner_subsample_rate,
    src comp        "cr_lib martian set_aligner_subsample_rate",
) using (
    mem_gb   = 8,
    threads  = 1,
    volatile = strict,
)

stage SET_TARGETED_UMI_FILTER(
    in  bui[]       bc_umi_info,
    in  frf.bincode feature_reference,
    out int         umi_read_count_threshold,
    out json        summary,
    src comp        "cr_lib martian set_targeted_umi_filter",
) using (
    mem_gb   = 8,
    threads  = 1,
    volatile = strict,
)

stage MULTI_SETUP_CHUNKS(
    in  string sample_id,
    in  map[]  sample_def,
    in  string chemistry_name,
    in  map    custom_chemistry_def,
    in  string default_library_type,
    out map[]  chunks,
    out map    chemistry_def,
    out string barcode_whitelist,
    src comp   "cr_lib martian setup_chunks",
)

stage SUBSAMPLE_BARCODES(
    in  bcc.bincode corrected_barcode_counts,
    out blf.json    barcode_subset,
    src comp        "cr_lib martian subsample_barcodes",
) using (
    mem_gb   = 4,
    threads  = 1,
    volatile = strict,
)

stage WRITE_GENE_INDEX(
    in  path reference_path,
    out json gene_index,
    src comp "cr_lib martian write_gene_index",
) using (
    mem_gb   = 6,
    threads  = 1,
    volatile = strict,
)

stage WRITE_MOLECULE_INFO(
    in  int         gem_well,
    in  bui[]       counts_bc_order,
    in  path        reference_path,
    in  map[]       read_chunks,
    in  frf.bincode feature_reference,
    in  string      barcode_whitelist,
    in  csv         filtered_barcodes,
    in  json        target_panel_summary,
    in  string      target_set_name,
    in  json        matrix_computer_summary,
    in  int         recovered_cells,
    in  int         force_cells,
    in  bool        include_introns,
    in  string      multi_config_sha,
    out h5          output,
    out json        summary,
    src comp        "cr_lib martian write_molecule_info",
) using (
    mem_gb   = 8,
    threads  = 1,
    volatile = strict,
)

stage RUN_ENCLONE(
    in  path   vdj_reference_path,
    in  json   contig_annotations,
    in  string receptor,
    out json   summary,
    out pb     enclone_output,
    out fa     donor_ref_fa,
    src comp   "cr_lib martian assigner",
) using (
    mem_gb  = 5,
    threads = -4,
)

stage WRITE_CLONOTYPE_OUTS(
    in  string receptor,
    in  pb     enclone_output,
    out csv    clonotypes_csv,
    src comp   "cr_lib martian write_clonotype_outs",
) using (
    mem_gb = 8,
)

stage FILL_CLONOTYPE_INFO(
    in  json contig_annotations,
    in  pb   enclone_output,
    out json all_contig_annotations_json,
    src comp "cr_lib martian fill_clonotype_info",
)

stage WRITE_CONCAT_REF_OUTS(
    in  pb        enclone_output,
    in  json      all_contig_annotations_json,
    out bam       concat_ref_bam,
    out bam.bai   concat_ref_bam_bai,
    out fasta     concat_ref_fasta,
    out fasta.fai concat_ref_fasta_fai,
    src comp      "cr_lib martian write_concat_ref_outs",
) using (
    mem_gb  = 4,
    threads = 4,
)

stage WRITE_CONSENSUS_BAM(
    in  pb      enclone_output,
    in  json    all_contig_annotations_json,
    out bam     consensus_bam,
    out bam.bai consensus_bam_bai,
    src comp    "cr_lib martian write_consensus_bam",
) using (
    mem_gb  = 4,
    threads = 4,
)

stage WRITE_CONSENSUS_TXT(
    in  pb        enclone_output,
    out fasta     consensus_fasta,
    out fasta.fai consensus_fasta_fai,
    out csv       consensus_annotations_csv,
    src comp      "cr_lib martian write_consensus_txt",
) using (
    mem_gb  = 4,
    threads = 4,
)

stage ASSEMBLE_VDJ(
    in  bincode.lz4[] bc_sorted_rna_reads,
    in  bool          paired_end,
    in  path          vdj_reference_path,
    in  string        receptor,
    in  int           n50_n50_rpu,
    in  int           npairs,
    in  bool          denovo,
    in  int           force_cells,
    in  path          inner_enrichment_primers,
    in  int           total_read_pairs,
    in  json          corrected_bc_counts,
    out bam           contig_bam,
    out bam.bai       contig_bam_bai,
    out tsv           summary_tsv,
    out tsv           umi_summary_tsv,
    out json          metrics_summary_json,
    out json          contig_annotations,
    out csv           barcode_support,
    out json[]        barcodes_in_chunks,
    out arp.bincode   assemblable_reads_per_bc,
    out txt           align_info,
    out fastq         unmapped_sample_fastq,
    out txt           report,
    src comp          "cr_lib martian assembly",
) split (
    in  bincode.lz4   chunk_rna_reads,
    in  bool          perf_track,
    in  int           chunk_id,
    out json          barcodes_in_chunk,
    out bin           barcode_data,
    out bin           barcode_data_sum,
    out bin           barcode_data_brief,
    out bincode       outs_builder,
)

stage CREATE_AIRR_TSV(
    in  json  contig_annotations,
    in  fasta concat_ref_fasta,
    out tsv   airr_annotations,
    src comp  "cr_lib martian airr_filter",
)

stage WRITE_CONTIG_OUTS(
    in  json        contig_annotations,
    in  int         total_read_pairs,
    in  json        corrected_bc_counts,
    in  arp.bincode assemblable_reads_per_bc,
    out fastq       contig_fastq,
    out fastq       filtered_contig_fastq,
    out fasta       contig_fasta,
    out fasta.fai   contig_fasta_fai,
    out fasta       filtered_contig_fasta,
    out bed         annotations_bed,
    out json        cell_barcodes,
    out json        paired_cell_barcodes,
    out json        summary,
    src comp        "cr_lib martian write_contig_outs",
)

stage HANDLE_GEX_CELLS(
    in  json asm_contig_annotations,
    in  csv  filtered_barcodes,
    in  bool is_antibody_only,
    in  bool is_non_targeted_gex,
    out json contig_annotations,
    src comp "cr_lib martian handle_gex_cells",
)

stage WRITE_ANN_CSV(
    in  json all_contig_annotations_json,
    out csv  all_contig_annotations_csv,
    out csv  filtered_contig_annotations_csv,
    src comp "cr_lib martian write_ann_csv",
)

stage PROCESS_VDJ_PROTO(
    in  VdjAggrCsvLibrary[] libraries,
    in  map                 count_gem_well_map,
    out string              receptor,
    out map                 gem_well_map,
    src comp                "cr_lib martian process_vdj_proto",
)

stage WRITE_ANNOTATION_JSON(
    in  VdjAggrCsvLibrary[] libraries,
    in  map                 gem_well_map,
    in  string              receptor,
    out json[]              contig_ann_json_files,
    out csv                 enclone_input_csv,
    out em.json             enclone_gem_well_meta,
    out path                vdj_reference_path,
    out json                combined_ann_json,
    src comp                "cr_lib martian write_ann_json",
) split (
    in  int                 chunk_id,
    out json                chunk_ann_json,
    out map                 enclone_meta_row,
    out map                 enclone_gem_well_info,
)

stage RUN_ENCLONE_AGGR(
    in  json[]  contig_ann_json_files,
    in  csv     enclone_input_csv,
    in  em.json enclone_gem_well_meta,
    in  path    vdj_reference_path,
    out pb      enclone_output,
    out fa      donor_ref_fa,
    src comp    "cr_lib martian run_enclone_aggr",
) using (
    mem_gb  = 8,
    threads = 4,
)

stage PARSE_AGGR_CSV(
    in  path           pipestance_root,
    in  csv            aggregation_csv,
    out csv            aggregation_csv,
    out map[]          count_libraries,
    out VdjAggrInput[] vdj_aggr_inputs,
    out bool           disable_count_aggr,
    out bool           disable_vdj_aggr,
    src comp           "cr_lib martian parse_aggr_csv",
)

stage WRITE_CONTIG_PROTO(
    in  path   vdj_reference_path,
    in  json   contig_annotations_json,
    in  string receptor,
    in  int[]  gem_wells,
    in  json   cell_barcodes,
    in  string sample_id,
    in  string sample_desc,
    in  string multi_config_sha,
    out pb     vdj_contig_info,
    src comp   "cr_lib martian write_contig_proto",
)

stage MATCH_VDJ_AGGR_OUTS(
    in  string[]       receptors,
    in  csv[]          clonotypes,
    in  fa[]           donor_ref_fas,
    in  fasta[]        consensus_fastas,
    in  path[]         vdj_reference_paths,
    in  csv[]          filtered_contig_annotations_csvs,
    in  csv[]          consensus_annotations_csvs,
    in  html[]         web_summaries,
    in  vloupe[]       vloupes,
    out VdjAggrResults vdj_t_results,
    out VdjAggrResults vdj_b_results,
    out path           vdj_reference_path,
    src comp           "cr_lib martian match_vdj_outs",
)

stage WRITE_AGGR_ANN(
    in  em.json enclone_gem_well_meta,
    in  csv     annotation_csv,
    out csv     augmented_annotation_csv,
    src comp    "cr_lib martian write_aggr_ann",
)

stage WRITE_WEB_SUMMARY_JSON(
    in  VdjAggrCsvLibrary[] libraries,
    in  pb                  enclone_output,
    in  em.json             enclone_gem_well_meta,
    in  string              sample_id,
    in  string              sample_desc,
    in  csv                 clonotypes_csv,
    in  string              receptor,
    out json                web_summary_content,
    out json                per_origin_hist,
    src comp                "cr_lib martian write_ws_json",
)

#
# @include "_basic_sc_rna_counter_stages.mro"
#

stage FILTER_BARCODES(
    in  string      sample_id,
    in  h5          matrices_h5,
    in  csv         barcode_correction_csv,
    in  bool        is_antibody_only,
    in  path        reference_path,
    in  int[]       gem_groups,
    in  map         chemistry_def,
    in  CellCalling config,
    out json        summary,
    out csv         filtered_barcodes,
    out csv         aggregate_barcodes,
    out h5          filtered_matrices_h5,
    out path        filtered_matrices_mex,
    out csv         nonambient_calls,
    src py          "../rna/stages/counter/filter_barcodes",
) split (
) using (
    mem_gb   = 8,
    volatile = strict,
)

stage SUMMARIZE_BASIC_REPORTS(
    in  h5     matrices_h5,
    in  csv    filtered_barcodes,
    in  csv    per_barcode_metrics,
    in  json   matrix_computer_summary,
    in  h5     barcode_summary,
    in  int    recovered_cells,
    in  path   reference_path,
    in  string barcode_whitelist,
    in  int[]  gem_groups,
    in  json[] summary_jsons,
    out json   summary,
    src py     "../rna/stages/counter/summarize_basic_reports",
) split (
) using (
    volatile = strict,
)

stage SUBSAMPLE_READS(
    in  h5     molecule_info,
    in  csv    filtered_barcodes,
    in  string target_mode,
    out json   summary,
    out pickle merged_metrics,
    src py     "../rna/stages/counter/subsample_reads",
) split (
    in  int    chunk_start,
    in  int    chunk_len,
    in  map[]  subsample_info,
    out pickle metrics,
) using (
    mem_gb   = 4,
    volatile = strict,
)

#
# @include "_slfe_cells_reporter.mro"
#

pipeline _SLFE_CELLS_REPORTER(
    in  string      barcode_whitelist,
    in  path        reference_path,
    in  int         recovered_cells,
    in  int         force_cells,
    in  frf.bincode slfe_feature_reference,
    in  json        target_panel_summary,
    in  string      target_set_name,
    in  h5          matrices_h5,
    in  map[]       read_chunks,
    in  int         gem_well,
    in  bui[]       report_mol_inputs,
    in  json        matrix_computer_summary,
    in  h5          barcode_summary,
    in  csv         filtered_barcodes,
    in  json        filter_barcodes_summary,
    in  csv         per_barcode_metrics,
    in  bool        include_introns,
    in  string      multi_config_sha,
    out json        summary,
    out h5          molecule_info,
)
{
    call WRITE_MOLECULE_INFO(
        gem_well                = self.gem_well,
        counts_bc_order         = self.report_mol_inputs,
        reference_path          = self.reference_path,
        read_chunks             = self.read_chunks,
        feature_reference       = self.slfe_feature_reference,
        target_panel_summary    = self.target_panel_summary,
        target_set_name         = self.target_set_name,
        barcode_whitelist       = self.barcode_whitelist,
        matrix_computer_summary = self.matrix_computer_summary,
        recovered_cells         = self.recovered_cells,
        force_cells             = self.force_cells,
        filtered_barcodes       = self.filtered_barcodes,
        include_introns         = self.include_introns,
        multi_config_sha        = self.multi_config_sha,
    )

    call SUBSAMPLE_READS(
        molecule_info     = WRITE_MOLECULE_INFO.output,
        filtered_barcodes = self.filtered_barcodes,
        target_mode       = null,
    ) using (
        volatile = true,
    )

    call SUMMARIZE_BASIC_REPORTS(
        matrices_h5             = self.matrices_h5,
        filtered_barcodes       = self.filtered_barcodes,
        per_barcode_metrics     = self.per_barcode_metrics,
        matrix_computer_summary = self.matrix_computer_summary,
        barcode_summary         = self.barcode_summary,
        recovered_cells         = self.recovered_cells,
        reference_path          = self.reference_path,
        barcode_whitelist       = self.barcode_whitelist,
        gem_groups              = [self.gem_well],
        summary_jsons           = [
            self.matrix_computer_summary,
            SUBSAMPLE_READS.summary,
            WRITE_MOLECULE_INFO.summary,
            self.filter_barcodes_summary,
        ],
    )

    return (
        summary       = SUMMARIZE_BASIC_REPORTS.summary,
        molecule_info = WRITE_MOLECULE_INFO.output,
    )
}

#
# @include "_slfe_partial_first_pass.mro"
#

# Inputs copied crom _cr_lib_stages. Cleaner way to do this?
pipeline _SLFE_PARTIAL_FIRST_PASS(
    in  int          gem_well,
    in  map[]        read_chunks,
    in  path         reference_path,
    in  shard[]      valid_reads,
    in  shard[]      corrected_reads,
    in  shard[]      invalid_reads,
    in  fbc.bincode  feature_counts,
    in  frf.bincode  feature_reference,
    in  csv          target_set,
    in  map          chemistry_def,
    in  bool         include_introns,
    in  string       aligner,
    in  bool         is_pd,
    in  int          trim_polya_min_score,
    in  int          trim_tso_min_score,
    in  tbcc.bincode total_barcode_counts,
    in  bcc.bincode  corrected_barcode_counts,
    out int          umi_read_count_threshold,
    out json         umi_filtering_summary,
)
{
    call SUBSAMPLE_BARCODES(
        corrected_barcode_counts = self.corrected_barcode_counts,
    )

    call ALIGN_AND_COUNT as INITIAL_ALIGN_AND_COUNT(
        gem_well                    = self.gem_well,
        read_chunks                 = self.read_chunks,
        reference_path              = self.reference_path,
        valid_reads                 = self.valid_reads,
        corrected_reads             = self.corrected_reads,
        invalid_reads               = self.invalid_reads,
        feature_counts              = self.feature_counts,
        feature_reference           = self.feature_reference,
        target_set                  = self.target_set,
        chemistry_def               = self.chemistry_def,
        include_introns             = self.include_introns,
        aligner                     = self.aligner,
        aligner_subsample_rate      = null,
        is_pd                       = self.is_pd,
        transcriptome_min_score     = 30,
        trim_polya_min_score        = self.trim_polya_min_score,
        trim_tso_min_score          = self.trim_tso_min_score,
        targeted_umi_min_read_count = null,
        total_barcode_counts        = self.total_barcode_counts,
        barcode_subset              = SUBSAMPLE_BARCODES.barcode_subset,
    )

    call SET_TARGETED_UMI_FILTER(
        bc_umi_info       = INITIAL_ALIGN_AND_COUNT.bc_umi_info,
        feature_reference = self.feature_reference,
    )

    return (
        umi_read_count_threshold = SET_TARGETED_UMI_FILTER.umi_read_count_threshold,
        umi_filtering_summary    = SET_TARGETED_UMI_FILTER.summary,
    )
}

#
# @include "_slfe_matrix_computer.mro"
#

pipeline _SLFE_MATRIX_COMPUTER(
    in  string            sample_id,
    in  map               chemistry_def,
    in  string            barcode_whitelist,
    in  json              barcodes_under_tissue,
    in  bool              is_pd,
    in  map[]             chunks,
    in  path              reference_path,
    in  string[]          libraries_to_translate,
    in  float             subsample_rate,
    in  int               initial_reads,
    in  int               r1_length,
    in  int               r2_length,
    in  int               trim_polya_min_score,
    in  int               trim_tso_min_score,
    in  csv               feature_reference,
    in  csv               target_features,
    in  csv               target_set,
    in  string            target_set_name,
    in  bool              include_introns,
    in  string            aligner,
    in  bool              disable_target_umi_filter,
    in  int               rps_limit,
    # Note: _SLFE_MATRIX_COMPUTER processes data from a single gem well.
    in  int               gem_well,
    out frf.bincode       slfe_feature_reference,
    out csv               barcode_correction_csv,
    out h5                barcode_summary,
    out h5                raw_gene_bc_matrices_h5,
    out path              raw_gene_bc_matrices_mex,
    out fastq[]           read1s,
    out bui[]             report_mol_inputs,
    out json              summary,
    out ann.bincode.lz4[] annotation_files,
    out csv               per_barcode_metrics,
    out bmsf[]            per_barcode_metrics_shard,
    out bui[]             bc_umi_info,
    out path              bam_header,
    out asf[]             alignments,
)
{
    call MAKE_SHARD(
        gem_well               = self.gem_well,
        chemistry_def          = self.chemistry_def,
        read_chunks            = self.chunks,
        barcode_whitelist      = self.barcode_whitelist,
        r1_length              = self.r1_length,
        r2_length              = self.r2_length,
        subsample_rate         = self.subsample_rate,
        initial_read_pairs     = self.initial_reads,
        reference_path         = self.reference_path,
        target_features        = self.target_features,
        target_set_name        = self.target_set_name,
        feature_reference_path = self.feature_reference,
        libraries_to_translate = self.libraries_to_translate,
    )

    call BARCODE_CORRECTION(
        gem_well               = self.gem_well,
        barcode_counts         = MAKE_SHARD.barcode_counts,
        barcode_whitelist      = self.barcode_whitelist,
        invalid_uncorrected    = MAKE_SHARD.invalid,
        valid_read_metrics     = MAKE_SHARD.bc_correct_summary,
        libraries_to_translate = self.libraries_to_translate,
    )

    call _SLFE_PARTIAL_FIRST_PASS(
        gem_well                 = self.gem_well,
        read_chunks              = self.chunks,
        reference_path           = self.reference_path,
        valid_reads              = MAKE_SHARD.valid,
        corrected_reads          = BARCODE_CORRECTION.valid_corrected,
        invalid_reads            = BARCODE_CORRECTION.invalid,
        feature_counts           = MAKE_SHARD.feature_counts,
        feature_reference        = MAKE_SHARD.feature_reference,
        target_set               = self.target_set,
        chemistry_def            = self.chemistry_def,
        include_introns          = self.include_introns,
        aligner                  = self.aligner,
        is_pd                    = self.is_pd,
        trim_polya_min_score     = self.trim_polya_min_score,
        trim_tso_min_score       = self.trim_tso_min_score,
        total_barcode_counts     = BARCODE_CORRECTION.total_barcode_counts,
        corrected_barcode_counts = BARCODE_CORRECTION.corrected_barcode_counts,
    ) using (
        disabled = self.disable_target_umi_filter,
    )

    call SET_ALIGNER_SUBSAMPLE_RATE(
        rps_limit                = self.rps_limit,
        barcodes_under_tissue    = self.barcodes_under_tissue,
        corrected_barcode_counts = BARCODE_CORRECTION.corrected_barcode_counts,
    )

    call ALIGN_AND_COUNT(
        gem_well                    = self.gem_well,
        read_chunks                 = self.chunks,
        reference_path              = self.reference_path,
        valid_reads                 = MAKE_SHARD.valid,
        corrected_reads             = BARCODE_CORRECTION.valid_corrected,
        invalid_reads               = BARCODE_CORRECTION.invalid,
        feature_counts              = MAKE_SHARD.feature_counts,
        feature_reference           = MAKE_SHARD.feature_reference,
        target_set                  = self.target_set,
        chemistry_def               = self.chemistry_def,
        include_introns             = self.include_introns,
        aligner                     = self.aligner,
        aligner_subsample_rate      = SET_ALIGNER_SUBSAMPLE_RATE.aligner_subsample_rate,
        is_pd                       = self.is_pd,
        transcriptome_min_score     = 30,
        trim_polya_min_score        = self.trim_polya_min_score,
        trim_tso_min_score          = self.trim_tso_min_score,
        targeted_umi_min_read_count = _SLFE_PARTIAL_FIRST_PASS.umi_read_count_threshold,
        total_barcode_counts        = BARCODE_CORRECTION.total_barcode_counts,
        barcode_subset              = null,
    )

    call COLLATE_METRICS(
        per_barcode_metrics = ALIGN_AND_COUNT.per_barcode_metrics,
        reference_path      = self.reference_path,
        feature_reference   = MAKE_SHARD.feature_reference,
    )

    call WRITE_BARCODE_SUMMARY(
        unique_gem_groups = [self.gem_well],
        bc_umi_info       = ALIGN_AND_COUNT.bc_umi_info,
        barcode_whitelist = self.barcode_whitelist,
        feature_reference = MAKE_SHARD.feature_reference,
    )

    call WRITE_H5_MATRIX(
        gem_well          = self.gem_well,
        counts            = ALIGN_AND_COUNT.counts_bc_order,
        bcs               = BARCODE_CORRECTION.corrected_barcode_counts,
        barcode_whitelist = self.barcode_whitelist,
        feature_reference = MAKE_SHARD.feature_reference,
        chemistry_def     = self.chemistry_def,
        sample_id         = self.sample_id,
    )

    call WRITE_MATRIX_MARKET(
        gem_well          = self.gem_well,
        counts            = ALIGN_AND_COUNT.counts_bc_order,
        bcs               = BARCODE_CORRECTION.corrected_barcode_counts,
        barcode_whitelist = self.barcode_whitelist,
        feature_reference = MAKE_SHARD.feature_reference,
    )

    call MERGE_METRICS(
        summaries = [
            MAKE_SHARD.summary,
            BARCODE_CORRECTION.summary,
            _SLFE_PARTIAL_FIRST_PASS.umi_filtering_summary,
            COLLATE_METRICS.summary,
        ],
    )

    return (
        barcode_correction_csv    = ALIGN_AND_COUNT.barcode_summary,
        barcode_summary           = WRITE_BARCODE_SUMMARY.barcode_summary,
        raw_gene_bc_matrices_h5   = WRITE_H5_MATRIX.matrix,
        raw_gene_bc_matrices_mex  = WRITE_MATRIX_MARKET.feature_bc_matrix,
        read1s                    = MAKE_SHARD.read1s,
        report_mol_inputs         = ALIGN_AND_COUNT.bc_umi_info,
        summary                   = MERGE_METRICS.summary,
        slfe_feature_reference    = MAKE_SHARD.feature_reference,
        annotation_files          = ALIGN_AND_COUNT.annotation_files,
        per_barcode_metrics       = COLLATE_METRICS.per_barcode_metrics,
        per_barcode_metrics_shard = ALIGN_AND_COUNT.per_barcode_metrics,
        bc_umi_info               = ALIGN_AND_COUNT.bc_umi_info,
        bam_header                = ALIGN_AND_COUNT.bam_header,
        alignments                = ALIGN_AND_COUNT.pos_sorted,
    )
}

#
# @include "_basic_sc_rna_counter.mro"
#

pipeline _BASIC_SC_RNA_COUNTER(
    in  int               gem_well,
    in  string            sample_id,
    in  map               chemistry_def,
    in  string            barcode_whitelist,
    in  bool              is_antibody_only,
    in  bool              is_pd,
    in  map[]             chunks,
    in  path              reference_path,
    in  CellCalling       cell_calling_config,
    in  string[]          libraries_to_translate,
    in  float             subsample_rate,
    in  int               initial_reads,
    in  int               r1_length,
    in  int               r2_length,
    in  int               trim_polya_min_score,
    in  int               trim_tso_min_score,
    in  csv               feature_reference,
    in  csv               target_features,
    in  csv               target_set,
    in  string            target_set_name,
    in  json              target_panel_summary,
    in  bool              include_introns,
    in  string            aligner,
    in  bool              disable_target_umi_filter,
    in  int               rps_limit,
    in  string            multi_config_sha,
    in  bool              no_bam,
    out csv               filtered_barcodes,
    out csv               nonambient_cell_calls,
    out csv               barcode_correction_csv,
    out bam               possorted_genome_bam,
    out bam.bai           possorted_genome_bam_index,
    out json              summary,
    out h5                barcode_summary,
    out h5                molecule_info,
    out h5                raw_gene_bc_matrices_h5,
    out path              raw_gene_bc_matrices_mex,
    out h5                filtered_gene_bc_matrices_h5,
    out path              filtered_gene_bc_matrices_mex,
    out int[]             gem_groups,
    out fastq[]           read1s,
    out ann.bincode.lz4[] annotation_files,
    # everything below here is needed only for gem group merging
    out csv               per_barcode_metrics,
    out bmsf[]            per_barcode_metrics_shard,
    out bui[]             bc_umi_info,
    out path              bam_header,
    out asf[]             alignments,
    out string            barcode_whitelist,
    out map[]             read_chunks,
    out string            target_set_name,
    out frf.bincode       slfe_feature_reference,
)
{
    call _SLFE_MATRIX_COMPUTER as _MATRIX_COMPUTER(
        gem_well                  = self.gem_well,
        sample_id                 = self.sample_id,
        chemistry_def             = self.chemistry_def,
        barcode_whitelist         = self.barcode_whitelist,
        barcodes_under_tissue     = self.cell_calling_config.cell_barcodes,
        is_pd                     = self.is_pd,
        chunks                    = self.chunks,
        reference_path            = self.reference_path,
        libraries_to_translate    = self.libraries_to_translate,
        subsample_rate            = self.subsample_rate,
        initial_reads             = self.initial_reads,
        r1_length                 = self.r1_length,
        r2_length                 = self.r2_length,
        trim_polya_min_score      = self.trim_polya_min_score,
        trim_tso_min_score        = self.trim_tso_min_score,
        feature_reference         = self.feature_reference,
        target_features           = self.target_features,
        target_set                = self.target_set,
        target_set_name           = self.target_set_name,
        include_introns           = self.include_introns,
        aligner                   = self.aligner,
        disable_target_umi_filter = self.disable_target_umi_filter,
        rps_limit                 = self.rps_limit,
    )

    # create single-GEM BAM file
    call WRITE_POS_BAM(
        target_set_name   = self.target_set_name,
        read_chunks       = self.chunks,
        barcode_to_sample = null,
        *                 = _MATRIX_COMPUTER,
    ) using (
        disabled = self.no_bam,
    )

    call FILTER_BARCODES(
        sample_id              = self.sample_id,
        matrices_h5            = _MATRIX_COMPUTER.raw_gene_bc_matrices_h5,
        barcode_correction_csv = _MATRIX_COMPUTER.barcode_correction_csv,
        config                 = self.cell_calling_config,
        gem_groups             = [self.gem_well],
        chemistry_def          = self.chemistry_def,
        is_antibody_only       = self.is_antibody_only,
        reference_path         = self.reference_path,
    )

    call _SLFE_CELLS_REPORTER as _CELLS_REPORTER(
        gem_well                = self.gem_well,
        barcode_whitelist       = self.barcode_whitelist,
        reference_path          = self.reference_path,
        recovered_cells         = self.cell_calling_config.recovered_cells,
        force_cells             = self.cell_calling_config.force_cells,
        slfe_feature_reference  = _MATRIX_COMPUTER.slfe_feature_reference,
        target_panel_summary    = self.target_panel_summary,
        target_set_name         = self.target_set_name,
        matrices_h5             = _MATRIX_COMPUTER.raw_gene_bc_matrices_h5,
        read_chunks             = self.chunks,
        report_mol_inputs       = _MATRIX_COMPUTER.report_mol_inputs,
        matrix_computer_summary = _MATRIX_COMPUTER.summary,
        barcode_summary         = _MATRIX_COMPUTER.barcode_summary,
        filtered_barcodes       = FILTER_BARCODES.filtered_barcodes,
        filter_barcodes_summary = FILTER_BARCODES.summary,
        per_barcode_metrics     = _MATRIX_COMPUTER.per_barcode_metrics,
        include_introns         = self.include_introns,
        multi_config_sha        = self.multi_config_sha,
    )

    return (
        filtered_barcodes             = FILTER_BARCODES.filtered_barcodes,
        nonambient_cell_calls         = FILTER_BARCODES.nonambient_calls,
        barcode_correction_csv        = _MATRIX_COMPUTER.barcode_correction_csv,
        possorted_genome_bam          = WRITE_POS_BAM.pos_sorted_bam.bam_file,
        possorted_genome_bam_index    = WRITE_POS_BAM.pos_sorted_bam.bam_index_file,
        summary                       = _CELLS_REPORTER.summary,
        barcode_summary               = _MATRIX_COMPUTER.barcode_summary,
        molecule_info                 = _CELLS_REPORTER.molecule_info,
        raw_gene_bc_matrices_h5       = _MATRIX_COMPUTER.raw_gene_bc_matrices_h5,
        raw_gene_bc_matrices_mex      = _MATRIX_COMPUTER.raw_gene_bc_matrices_mex,
        filtered_gene_bc_matrices_h5  = FILTER_BARCODES.filtered_matrices_h5,
        filtered_gene_bc_matrices_mex = FILTER_BARCODES.filtered_matrices_mex,
        gem_groups                    = [self.gem_well],
        read1s                        = _MATRIX_COMPUTER.read1s,
        annotation_files              = _MATRIX_COMPUTER.annotation_files,
        # everything below here is needed only for gem well merging
        bc_umi_info                   = _MATRIX_COMPUTER.bc_umi_info,
        per_barcode_metrics           = _MATRIX_COMPUTER.per_barcode_metrics,
        per_barcode_metrics_shard     = _MATRIX_COMPUTER.per_barcode_metrics_shard,
        bam_header                    = _MATRIX_COMPUTER.bam_header,
        alignments                    = _MATRIX_COMPUTER.alignments,
        read_chunks                   = self.chunks,
        target_set_name               = self.target_set_name,
        barcode_whitelist             = self.barcode_whitelist,
        slfe_feature_reference        = _MATRIX_COMPUTER.slfe_feature_reference,
    )
}

#
# @include "_common_stages.mro"
#

stage CELLRANGER_PREFLIGHT(
    in  bool     full_check,
    in  map[]    sample_def,
    in  string   chemistry_name,
    in  map      custom_chemistry_def,
    in  path     reference_path,
    in  csv      feature_reference,
    in  int      recovered_cells,
    in  int      force_cells,
    in  string[] allowed_chems,
    in  int      r1_length,
    in  int      r2_length,
    src py       "../rna/stages/common/cellranger_preflight",
) using (
    mem_gb   = 8,
    volatile = strict,
)

stage DISABLE_FEATURE_STAGES(
    in  map[] sample_def,
    out bool  disable_crispr,
    out bool  disable_antibody,
    out bool  disable_multiplexing,
    src py    "../rna/stages/common/disable_feature_stages",
)

stage PARSE_TARGET_FEATURES(
    in  map[]  sample_def,
    in  path   reference_path,
    in  json   gene_index,
    in  bool   no_target_umi_filter,
    in  int    rps_limit,
    out fa     bait_fasta,
    out csv    target_panel,
    out csv    target_gene_indices,
    out bool   disable_targeted,
    out bool   disable_target_umi_filter,
    out int    rps_limit,
    out string target_set_name,
    out json   summary,
    src py     "../rna/stages/common/parse_target_features",
) using (
    mem_gb = 4,
)

#
# @include "_spatial_reporting_stages.mro"
#

stage SPATIAL_REPORTER(
    in  json[] summaries,
    in  string sample_id,
    in  string sample_desc,
    in  string slide_serial_info,
    in  path   reference_path,
    in  path   analysis,
    in  h5     barcode_summary_h5,
    in  csv    filtered_barcodes,
    in  string barcode_whitelist,
    in  int[]  gem_groups,
    in  h5     matrix,
    in  json   scalefactors,
    in  jpg    aligned_fiducials,
    in  float  fraction_under_tissue,
    in  png    tissue_hires_image,
    in  png    tissue_lowres_image,
    in  jpg    detected_tissue_image,
    in  csv    tissue_positions_list,
    in  string target_set_name,
    in  csv    per_feature_metrics_csv,
    out path   spatial,
    out html   web_summary,
    out json   metrics_summary_json,
    out csv    metrics_summary_csv,
    src py     "../rna/stages/spatial/spatial_reporter",
) using (
    mem_gb = 4,
)

#
# @include "_sc_rna_targeted_analyzer_stages.mro"
#

stage SUMMARIZE_TARGETED_ANALYSIS(
    in  json[] summaries,
    out json   summary,
    src py     "../rna/stages/targeted/summarize_targeted_analysis",
)

stage CALCULATE_TARGETED_METRICS(
    in  h5   molecule_info,
    in  h5   filtered_gene_bc_matrices,
    in  json basic_counter_summary,
    in  json targeted_summary,
    out json summary,
    out csv  per_feature_metrics_csv,
    src py   "../rna/stages/targeted/calculate_targeted_metrics",
) split (
)

#
# @include "_targeted_analyzer.mro"
#

pipeline _TARGETED_ANALYZER(
    in  h5   molecule_info,
    in  h5   filtered_gene_bc_matrices,
    in  csv  filtered_barcodes,
    in  json basic_counter_summary,
    in  json targeted_summary,
    out json targeted_analysis_metrics,
    out csv  per_feature_metrics_csv,
)
{
    call CALCULATE_TARGETED_METRICS(
        molecule_info             = self.molecule_info,
        filtered_gene_bc_matrices = self.filtered_gene_bc_matrices,
        basic_counter_summary     = self.basic_counter_summary,
        targeted_summary          = self.targeted_summary,
    )

    call SUBSAMPLE_READS as SUBSAMPLE_ON_TARGET_READS(
        molecule_info     = self.molecule_info,
        filtered_barcodes = self.filtered_barcodes,
        target_mode       = "ontarget",
    )

    call SUBSAMPLE_READS as SUBSAMPLE_OFF_TARGET_READS(
        molecule_info     = self.molecule_info,
        filtered_barcodes = self.filtered_barcodes,
        target_mode       = "offtarget",
    )

    call SUMMARIZE_TARGETED_ANALYSIS(
        summaries = [
            CALCULATE_TARGETED_METRICS.summary,
            SUBSAMPLE_ON_TARGET_READS.summary,
            SUBSAMPLE_OFF_TARGET_READS.summary,
        ],
    )

    return (
        targeted_analysis_metrics = SUMMARIZE_TARGETED_ANALYSIS.summary,
        per_feature_metrics_csv   = CALCULATE_TARGETED_METRICS.per_feature_metrics_csv,
    )
}

#
# @include "spatial_rna_counter.mro"
#

pipeline SPATIAL_RNA_COUNTER(
    in  string            sample_id,
    in  map[]             sample_def,
    in  string            slide_serial_capture_area,
    in  map[]             chunks,
    in  map               chemistry_def,
    in  string            barcode_whitelist,
    in  path              reference_path,
    in  int               recovered_cells,
    in  int               force_cells,
    in  float             subsample_rate,
    in  int               initial_reads,
    in  string            sample_desc,
    in  int               r1_length                      "Trim input R1 to this length (optional)",
    in  int               r2_length                      "Trim input R2 to this length (optional)",
    in  int               trim_polya_min_score,
    in  int               trim_tso_min_score,
    in  bool              no_bam,
    in  bool              no_secondary_analysis,
    in  bool              no_target_umi_filter,
    in  int               rps_limit,
    in  string            aligner,
    in  bool              is_pd,
    in  json              barcodes_under_tissue,
    in  float             fraction_under_tissue,
    in  json              alignment_metrics,
    in  jpg               aligned_fiducials,
    in  png               tissue_hires_img,
    in  png               tissue_lowres_img,
    in  jpg               detected_tissue_img,
    in  csv               tissue_positions_list,
    in  json              image_scale_factors,
    in  csv               feature_reference,
    in  bool              is_antibody_only,
    out json              gene_index,
    out bam               possorted_genome_bam,
    out bam.bai           possorted_genome_bam_index,
    out path              spatial,
    out json              metrics_summary_json,
    out csv               metrics_summary_csv,
    out html              web_summary,
    out h5                barcode_summary,
    out h5                molecule_info,
    out h5                raw_gene_bc_matrices_h5,
    out path              raw_gene_bc_matrices_mex,
    out h5                filtered_gene_bc_matrices_h5,
    out path              filtered_gene_bc_matrices_mex,
    out path              analysis,
    out path              analysis_csv,
    out fastq[]           read_fastqs,
    out int[]             gem_groups,
    out csv               filtered_barcodes,
    out csv               barcode_correction_csv,
    out ann.bincode.lz4[] annotation_files,
    out csv               per_barcode_metrics,
    out bool              disable_targeted,
    out csv               target_panel,
    out string            target_set_name,
    out csv               per_feature_metrics_csv,
    out fa                bait_fasta,
)
{
    call WRITE_GENE_INDEX(
        reference_path = self.reference_path,
    )

    # TODO:
    #    The stage PARSE_TARGET_FEATURES is called both in SPATIAL_RNA_COUNTER and SPATIAL_RNA_COUNTER_PD with same input parameters.
    #    This mirrors the SC/CR behavior, should this be the case or should we pass the outs from here instead of calling it twice?
    call PARSE_TARGET_FEATURES(
        reference_path       = self.reference_path,
        gene_index           = WRITE_GENE_INDEX.gene_index,
        sample_def           = self.sample_def,
        no_target_umi_filter = self.no_target_umi_filter,
        rps_limit            = self.rps_limit,
    )

    call _BASIC_SC_RNA_COUNTER as _BASIC_SPATIAL_RNA_COUNTER(
        gem_well                  = 1,
        sample_id                 = self.sample_id,
        chemistry_def             = self.chemistry_def,
        barcode_whitelist         = self.barcode_whitelist,
        is_antibody_only          = self.is_antibody_only,
        reference_path            = self.reference_path,
        cell_calling_config       = {
            cell_barcodes:          self.barcodes_under_tissue,
            force_cells:            self.force_cells,
            override_library_types: null,
            override_mode:          null,
            recovered_cells:        self.recovered_cells,
        },
        libraries_to_translate    = [],
        is_pd                     = self.is_pd,
        chunks                    = self.chunks,
        subsample_rate            = self.subsample_rate,
        initial_reads             = self.initial_reads,
        r1_length                 = self.r1_length,
        r2_length                 = self.r2_length,
        trim_polya_min_score      = self.trim_polya_min_score,
        trim_tso_min_score        = self.trim_tso_min_score,
        feature_reference         = self.feature_reference,
        target_features           = PARSE_TARGET_FEATURES.target_gene_indices,
        target_set                = PARSE_TARGET_FEATURES.target_panel,
        target_set_name           = PARSE_TARGET_FEATURES.target_set_name,
        target_panel_summary      = PARSE_TARGET_FEATURES.summary,
        include_introns           = false,
        aligner                   = self.aligner,
        disable_target_umi_filter = PARSE_TARGET_FEATURES.disable_target_umi_filter,
        rps_limit                 = PARSE_TARGET_FEATURES.rps_limit,
        multi_config_sha          = null,
        no_bam                    = self.no_bam,
    )

    call SC_RNA_ANALYZER as SPATIAL_RNA_ANALYZER(
        filtered_matrices_h5       = _BASIC_SPATIAL_RNA_COUNTER.filtered_gene_bc_matrices_h5,
        no_secondary_analysis      = self.no_secondary_analysis,
        aggr_library_info          = null,
        num_analysis_bcs           = null,
        num_pca_bcs                = null,
        num_pca_genes              = null,
        num_principal_comps        = null,
        chemistry_batch_correction = false,
        cbc_knn                    = null,
        cbc_alpha                  = null,
        cbc_sigma                  = null,
        cbc_realign_panorama       = null,
        max_clusters               = null,
        graphclust_neighbors       = null,
        neighbor_a                 = null,
        neighbor_b                 = null,
        tsne_perplexity            = null,
        tsne_input_pcs             = null,
        random_seed                = null,
        tsne_theta                 = null,
        use_genes                  = null,
        exclude_genes              = null,
        use_bcs                    = null,
        tsne_max_dims              = null,
        tsne_max_iter              = null,
        tsne_stop_lying_iter       = null,
        tsne_mom_switch_iter       = null,
        umap_n_neighbors           = null,
        umap_input_pcs             = null,
        umap_max_dims              = null,
        umap_min_dist              = null,
        umap_metric                = null,
        # NOTE: this is null because the cells are already forced in FILTER_BARCODES
        force_cells                = null,
        skip_multigenome_analysis  = true,
    )

    call _TARGETED_ANALYZER(
        molecule_info             = _BASIC_SPATIAL_RNA_COUNTER.molecule_info,
        filtered_gene_bc_matrices = _BASIC_SPATIAL_RNA_COUNTER.filtered_gene_bc_matrices_h5,
        filtered_barcodes         = _BASIC_SPATIAL_RNA_COUNTER.filtered_barcodes,
        basic_counter_summary     = _BASIC_SPATIAL_RNA_COUNTER.summary,
        targeted_summary          = PARSE_TARGET_FEATURES.summary,
    ) using (
        disabled = PARSE_TARGET_FEATURES.disable_targeted,
    )

    call SPATIAL_REPORTER(
        summaries               = [
            _BASIC_SPATIAL_RNA_COUNTER.summary,
            SPATIAL_RNA_ANALYZER.summary,
            self.alignment_metrics,
            _TARGETED_ANALYZER.targeted_analysis_metrics,
            PARSE_TARGET_FEATURES.summary,
        ],
        sample_id               = self.sample_id,
        slide_serial_info       = self.slide_serial_capture_area,
        sample_desc             = self.sample_desc,
        reference_path          = self.reference_path,
        barcode_summary_h5      = _BASIC_SPATIAL_RNA_COUNTER.barcode_summary,
        filtered_barcodes       = _BASIC_SPATIAL_RNA_COUNTER.filtered_barcodes,
        fraction_under_tissue   = self.fraction_under_tissue,
        barcode_whitelist       = self.barcode_whitelist,
        matrix                  = _BASIC_SPATIAL_RNA_COUNTER.raw_gene_bc_matrices_h5,
        analysis                = SPATIAL_RNA_ANALYZER.analysis,
        gem_groups              = _BASIC_SPATIAL_RNA_COUNTER.gem_groups,
        scalefactors            = self.image_scale_factors,
        tissue_hires_image      = self.tissue_hires_img,
        tissue_lowres_image     = self.tissue_lowres_img,
        aligned_fiducials       = self.aligned_fiducials,
        detected_tissue_image   = self.detected_tissue_img,
        tissue_positions_list   = self.tissue_positions_list,
        target_set_name         = PARSE_TARGET_FEATURES.target_set_name,
        per_feature_metrics_csv = _TARGETED_ANALYZER.per_feature_metrics_csv,
    )

    return (
        gene_index                    = WRITE_GENE_INDEX.gene_index,
        possorted_genome_bam          = _BASIC_SPATIAL_RNA_COUNTER.possorted_genome_bam,
        possorted_genome_bam_index    = _BASIC_SPATIAL_RNA_COUNTER.possorted_genome_bam_index,
        web_summary                   = SPATIAL_REPORTER.web_summary,
        spatial                       = SPATIAL_REPORTER.spatial,
        metrics_summary_json          = SPATIAL_REPORTER.metrics_summary_json,
        metrics_summary_csv           = SPATIAL_REPORTER.metrics_summary_csv,
        barcode_summary               = _BASIC_SPATIAL_RNA_COUNTER.barcode_summary,
        molecule_info                 = _BASIC_SPATIAL_RNA_COUNTER.molecule_info,
        raw_gene_bc_matrices_h5       = _BASIC_SPATIAL_RNA_COUNTER.raw_gene_bc_matrices_h5,
        raw_gene_bc_matrices_mex      = _BASIC_SPATIAL_RNA_COUNTER.raw_gene_bc_matrices_mex,
        filtered_gene_bc_matrices_h5  = _BASIC_SPATIAL_RNA_COUNTER.filtered_gene_bc_matrices_h5,
        filtered_gene_bc_matrices_mex = _BASIC_SPATIAL_RNA_COUNTER.filtered_gene_bc_matrices_mex,
        analysis                      = SPATIAL_RNA_ANALYZER.analysis,
        analysis_csv                  = SPATIAL_RNA_ANALYZER.analysis_csv,
        read_fastqs                   = _BASIC_SPATIAL_RNA_COUNTER.read1s,
        gem_groups                    = _BASIC_SPATIAL_RNA_COUNTER.gem_groups,
        filtered_barcodes             = _BASIC_SPATIAL_RNA_COUNTER.filtered_barcodes,
        barcode_correction_csv        = _BASIC_SPATIAL_RNA_COUNTER.barcode_correction_csv,
        annotation_files              = _BASIC_SPATIAL_RNA_COUNTER.annotation_files,
        per_barcode_metrics           = _BASIC_SPATIAL_RNA_COUNTER.per_barcode_metrics,
        disable_targeted              = PARSE_TARGET_FEATURES.disable_targeted,
        target_panel                  = PARSE_TARGET_FEATURES.target_panel,
        target_set_name               = PARSE_TARGET_FEATURES.target_set_name,
        per_feature_metrics_csv       = _TARGETED_ANALYZER.per_feature_metrics_csv,
        bait_fasta                    = PARSE_TARGET_FEATURES.bait_fasta,
    )
}

#
# @include "spatial_rna_counter_prep.mro"
#

pipeline SPATIAL_RNA_COUNTER_PREP(
    in  string   sample_id,
    in  map[]    sample_def,
    in  string   chemistry_name,
    in  map      custom_chemistry_def,
    in  path     reference_path,
    in  int      r1_length             "Trim input R1 to this length (optional)",
    in  int      r2_length             "Trim input R2 to this length (optional)",
    in  string[] allowed_chems,
    out map[]    chunks,
    out map      chemistry_def,
    out string   barcode_whitelist,
    out string   chemistry_type,
    out bool     is_antibody_only,
)
{
    call DETECT_CHEMISTRY as CHEMISTRY_DETECTOR(
        sample_def          = self.sample_def,
        reference_path      = self.reference_path,
        chemistry_name_spec = self.chemistry_name,
        allowed_chems       = self.allowed_chems,
        r1_length           = self.r1_length,
        r2_length           = self.r2_length,
    )

    call MULTI_SETUP_CHUNKS(
        sample_id            = self.sample_id,
        sample_def           = self.sample_def,
        chemistry_name       = CHEMISTRY_DETECTOR.chemistry_type,
        custom_chemistry_def = self.custom_chemistry_def,
        default_library_type = null,
    ) using (
        local    = true,
        volatile = true,
    )

    return (
        chunks            = MULTI_SETUP_CHUNKS.chunks,
        chemistry_def     = MULTI_SETUP_CHUNKS.chemistry_def,
        barcode_whitelist = MULTI_SETUP_CHUNKS.barcode_whitelist,
        chemistry_type    = CHEMISTRY_DETECTOR.chemistry_type,
        is_antibody_only  = CHEMISTRY_DETECTOR.is_antibody_only,
    )
}

#
# @include "_common_cloupe_stages.mro"
#

stage CLOUPE_PREPROCESS(
    in  string pipestance_type,
    in  string sample_id,
    in  string sample_desc,
    in  path   analysis,
    in  h5     filtered_gene_bc_matrices_h5,
    in  json   metrics_json,
    in  csv    aggregation_csv,
    in  json   gem_group_index_json,
    in  path[] tissue_image_paths,
    in  int    dark_images,
    in  csv    tissue_positions_list,
    in  txt    fiducial_positions_list,
    in  json   dzi_info,
    in  path[] dzi_tiles_paths,
    in  json   scale_factors_json,
    in  bool   no_secondary_analysis,
    in  string barcode_whitelist,
    in  json   loupe_map,
    in  string product_type,
    out cloupe output_for_cloupe,
    out json   gem_group_index_json,
    src py     "../rna/stages/cloupe/cloupe_preprocess",
) split (
)

#
# @include "_spatial_cloupe_stages.mro"
#

stage CLOUPE_TILE_IMAGES(
    in  path[] tissue_image_paths,
    in  int    tile_size,
    in  bool   skip_stage,
    in  bool   no_secondary_analysis,
    out json   dzi_info,
    out path[] dzi_tiles_paths,
    src py     "../rna/stages/cloupe/cloupe_tile_images",
) split (
) using (
    mem_gb = 2,
)

stage MERGE_TISSUE_FILES(
    in  map[] sample_defs,
    out csv   aggr_tissue_positions_list,
    out path  spatial,
    out json  loupe_map,
    src py    "../rna/stages/spatial/merge_tissue_files",
)

stage VERIFY_SPATIAL_CLOUPES(
    in  map[] sample_defs,
    src py    "../rna/stages/cloupe/verify_spatial_cloupes",
)

#
# @include "_spatial_imaging_stages.mro"
#

stage ALIGN_FIDUCIALS(
    in  png    downsampled_tissue_image,
    in  json   scalefactors_json,
    in  json   gpr_data,
    in  string reorientation_mode,
    in  path   loupe_alignment_file,
    in  string transform_method,
    out txt    spot_positions_list,
    out txt    fiducial_positions_list,
    out jpg    aligned_fiducials,
    out jpg    detected_keypoints,
    out json   scalefactors_json,
    out json   alignment_metrics,
    src py     "../rna/stages/spatial/align_fiducials",
) using (
    mem_gb  = 4,
    vmem_gb = 16,
) retain (
    detected_keypoints,
)

stage DETECT_TISSUE(
    in  png    downsampled_tissue_image,
    in  json   scalefactors_json,
    in  bool   skip_tissue_detection,
    in  path   spot_data_sel,
    in  path   loupe_alignment_file,
    in  json   gpr_data,
    in  txt    spot_positions_list,
    in  txt    fiducial_positions_list,
    in  string barcode_whitelist,
    out jpg    detected_tissue_image,
    out csv    tissue_positions_list,
    out json   barcodes_under_tissue,
    out float  fraction_under_tissue,
    src py     "../rna/stages/spatial/detect_tissue",
) using (
    mem_gb  = 4,
    vmem_gb = 16,
)

stage STANDARDIZE_IMAGES(
    in  path[] tissue_image_paths,
    in  path   spot_image_path,
    in  int    dark_images,
    out json   scalefactors_json,
    out png    tissue_hires_image,
    out png    tissue_lowres_image,
    out png    fiducial_hires_image,
    out png    spot_hires_image,
    src py     "../rna/stages/spatial/standardize_images",
) split (
) using (
    mem_gb = 2,
)

stage GPR_READER(
    in  string slide_serial_capture_area,
    in  path   loupe_alignment_file,
    in  gpr    gpr_file,
    in  string barcode_whitelist,
    out json   gpr_data,
    src py     "../rna/stages/spatial/gpr_reader",
)

#
# @include "_spatial_imaging_cs.mro"
#

pipeline _SPATIAL_IMAGING_CS(
    in  string slide_serial_capture_area  "Slide serial number and area id",
    in  path   loupe_alignment_file       "Path to Loupe-generated manual alignment file",
    in  gpr    gpr_file                   "Slide GPR file",
    in  string reorientation_mode         "rotate ('rotation') or rotate+mirror ('rotation+mirror') fiducial template to find best alignment",
    in  path[] tissue_image_paths         "Path(s) to slide image(s)",
    in  int    dark_images                "Path(s) to dark background images",
    in  string barcode_whitelist          "Whitelisted barcodes CSV",
    out jpg    aligned_fiducials          "Slide image annotated with fiducial alignment",
    out jpg    detected_tissue_image      "Slide image annotated with detected tissue",
    out csv    tissue_positions_list      "Slide position and tissue status of barcodes CSV",
    out txt    fiducial_positions_list    "Slide position of fiducial spots CSV",
    out json   barcodes_under_tissue      "Slide position and tissue status of barcodes JSON",
    out float  fraction_under_tissue      "Fraction of barcodes under tissue",
    out json   image_scalefactors         "Scale factors for hires and lowres images and fiducial and spot diameters",
    out json   alignment_metrics          "Metrics from fiducial alignment procedure",
    out png    tissue_hires_image         "Slide image scaled to 2000px in the largest dimension",
    out png    tissue_lowres_image        "Slide image scaled to 600px in the largest dimension",
)
{
    call GPR_READER(
        slide_serial_capture_area = self.slide_serial_capture_area,
        loupe_alignment_file      = self.loupe_alignment_file,
        gpr_file                  = self.gpr_file,
        barcode_whitelist         = self.barcode_whitelist,
    )

    call STANDARDIZE_IMAGES(
        tissue_image_paths = self.tissue_image_paths,
        dark_images        = self.dark_images,
        spot_image_path    = null,
    )

    call ALIGN_FIDUCIALS(
        downsampled_tissue_image = STANDARDIZE_IMAGES.fiducial_hires_image,
        scalefactors_json        = STANDARDIZE_IMAGES.scalefactors_json,
        gpr_data                 = GPR_READER.gpr_data,
        reorientation_mode       = self.reorientation_mode,
        loupe_alignment_file     = self.loupe_alignment_file,
        transform_method         = "rigid",
    )

    call DETECT_TISSUE(
        downsampled_tissue_image = STANDARDIZE_IMAGES.tissue_hires_image,
        scalefactors_json        = ALIGN_FIDUCIALS.scalefactors_json,
        skip_tissue_detection    = false,
        loupe_alignment_file     = self.loupe_alignment_file,
        gpr_data                 = GPR_READER.gpr_data,
        spot_positions_list      = ALIGN_FIDUCIALS.spot_positions_list,
        fiducial_positions_list  = ALIGN_FIDUCIALS.fiducial_positions_list,
        barcode_whitelist        = self.barcode_whitelist,
        spot_data_sel            = null,
    )

    return (
        aligned_fiducials       = ALIGN_FIDUCIALS.aligned_fiducials,
        fiducial_positions_list = ALIGN_FIDUCIALS.fiducial_positions_list,
        detected_tissue_image   = DETECT_TISSUE.detected_tissue_image,
        tissue_positions_list   = DETECT_TISSUE.tissue_positions_list,
        barcodes_under_tissue   = DETECT_TISSUE.barcodes_under_tissue,
        fraction_under_tissue   = DETECT_TISSUE.fraction_under_tissue,
        image_scalefactors      = ALIGN_FIDUCIALS.scalefactors_json,
        tissue_hires_image      = STANDARDIZE_IMAGES.tissue_hires_image,
        tissue_lowres_image     = STANDARDIZE_IMAGES.tissue_lowres_image,
        alignment_metrics       = ALIGN_FIDUCIALS.alignment_metrics,
    )
}

#
# @include "_spatial_preflights.mro"
#

stage SPACERANGER_PREFLIGHT(
    in  map[]    sample_def,
    in  string   chemistry_name,
    in  map      custom_chemistry_def,
    in  path     reference_path,
    in  int      recovered_cells,
    in  int      force_cells,
    in  string[] allowed_chems,
    in  int      r1_length,
    in  int      r2_length,
    in  path[]   tissue_image_paths,
    in  int      dark_images,
    in  path     loupe_alignment_file,
    in  gpr      gpr_file,
    in  string   slide_serial_capture_area,
    src py       "../rna/stages/common/spaceranger_preflight",
) split (
) using (
    mem_gb = 2,
)

stage SPACERANGER_PREFLIGHT_LOCAL(
    in  map[]    sample_def,
    in  string   chemistry_name,
    in  map      custom_chemistry_def,
    in  path     reference_path,
    in  int      recovered_cells,
    in  int      force_cells,
    in  string[] allowed_chems,
    in  int      r1_length,
    in  int      r2_length,
    in  path[]   tissue_image_paths,
    in  int      dark_images,
    in  path     loupe_alignment_file,
    in  gpr      gpr_file,
    in  string   slide_serial_capture_area,
    src py       "../rna/stages/common/spaceranger_preflight_local",
)

#
# @include "rna/spatial_rna_counter_cs.mro"
#

pipeline SPATIAL_RNA_COUNTER_CS(
    in  string  sample_id                      "A unique run id",
    in  map[]   sample_def                     "Sample definition",
    in  string  sample_desc                    "Sample description to embed in output files",
    in  string  slide_serial_capture_area      "Slide serial number and area id",
    in  path    loupe_alignment_file           "Path to Loupe-generated manual alignment file",
    in  gpr     gpr_file                       "Slide GPR file",
    in  path    reference_path                 "Path to reference",
    in  bool    no_bam                         "Skip generating BAM file outputs",
    in  bool    no_secondary_analysis          "Flag to disable clustering and dimensionality reduction",
    in  int     rps_limit                      "Subsample to at most NUM mean reads under tissue per spot for targeted gene expression [default: 15000]",
    in  int     r1_length                      "Trim input R1 to this length (optional)",
    in  int     r2_length                      "Trim input R2 to this length (optional)",
    in  int     trim_polya_min_score,
    in  int     trim_tso_min_score,
    in  path[]  tissue_image_paths             "Path to brightfield slide image or fluorescence (dark) images",
    in  int     dark_images                    "null or 0 for brightfield, 1 for fluoro channels, 2 for single pre-colorized image",
    in  string  reorientation_mode             "Set rotation or rotation+mirror to reorient input images",
    out html    web_summary                    "Run summary HTML",
    out path    spatial                        "Outputs of spatial pipeline",
    out csv     metrics_summary                "Run summary CSV",
    out bam     possorted_genome_bam           "BAM"                 "possorted_genome_bam.bam",
    out bam.bai possorted_genome_bam_index     "BAM index"           "possorted_genome_bam.bam.bai",
    out path    filtered_feature_bc_matrix     "Filtered feature-barcode matrices MEX",
    out h5      filtered_feature_bc_matrix_h5  "Filtered feature-barcode matrices HDF5"  "filtered_feature_bc_matrix.h5",
    out path    raw_feature_bc_matrix          "Unfiltered feature-barcode matrices MEX",
    out h5      raw_feature_bc_matrix_h5       "Unfiltered feature-barcode matrices HDF5"  "raw_feature_bc_matrix.h5",
    out path    analysis                       "Secondary analysis output CSV",
    out h5      molecule_info                  "Per-molecule read information",
    out cloupe  cloupe                         "Loupe Browser file",
    out csv     target_panel                   "Target Panel File",
)
{
    call SPACERANGER_PREFLIGHT(
        sample_def                = self.sample_def,
        chemistry_name            = "SPATIAL3Pv1",
        custom_chemistry_def      = null,
        reference_path            = self.reference_path,
        recovered_cells           = null,
        force_cells               = null,
        allowed_chems             = ["SPATIAL3Pv1"],
        r1_length                 = self.r1_length,
        r2_length                 = self.r2_length,
        tissue_image_paths        = self.tissue_image_paths,
        dark_images               = self.dark_images,
        loupe_alignment_file      = self.loupe_alignment_file,
        gpr_file                  = self.gpr_file,
        slide_serial_capture_area = self.slide_serial_capture_area,
    ) using (
        preflight = true,
    )

    call SPACERANGER_PREFLIGHT_LOCAL(
        sample_def                = self.sample_def,
        chemistry_name            = "SPATIAL3Pv1",
        custom_chemistry_def      = null,
        reference_path            = self.reference_path,
        recovered_cells           = null,
        force_cells               = null,
        allowed_chems             = ["SPATIAL3Pv1"],
        r1_length                 = self.r1_length,
        r2_length                 = self.r2_length,
        tissue_image_paths        = self.tissue_image_paths,
        dark_images               = self.dark_images,
        loupe_alignment_file      = self.loupe_alignment_file,
        gpr_file                  = self.gpr_file,
        slide_serial_capture_area = self.slide_serial_capture_area,
    ) using (
        local     = true,
        preflight = true,
    )

    call SPATIAL_RNA_COUNTER_PREP(
        sample_id            = self.sample_id,
        sample_def           = self.sample_def,
        chemistry_name       = "SPATIAL3Pv1",
        custom_chemistry_def = null,
        r1_length            = self.r1_length,
        r2_length            = self.r2_length,
        allowed_chems        = ["SPATIAL3Pv1"],
        reference_path       = self.reference_path,
    )

    call _SPATIAL_IMAGING_CS as SPATIAL_IMAGING_CS(
        slide_serial_capture_area = self.slide_serial_capture_area,
        loupe_alignment_file      = self.loupe_alignment_file,
        gpr_file                  = self.gpr_file,
        reorientation_mode        = self.reorientation_mode,
        tissue_image_paths        = self.tissue_image_paths,
        dark_images               = self.dark_images,
        barcode_whitelist         = SPATIAL_RNA_COUNTER_PREP.barcode_whitelist,
    )

    call SPATIAL_RNA_COUNTER(
        sample_id                 = self.sample_id,
        sample_def                = self.sample_def,
        sample_desc               = self.sample_desc,
        slide_serial_capture_area = self.slide_serial_capture_area,
        chunks                    = SPATIAL_RNA_COUNTER_PREP.chunks,
        chemistry_def             = SPATIAL_RNA_COUNTER_PREP.chemistry_def,
        barcode_whitelist         = SPATIAL_RNA_COUNTER_PREP.barcode_whitelist,
        subsample_rate            = null,
        initial_reads             = null,
        no_bam                    = self.no_bam,
        no_secondary_analysis     = self.no_secondary_analysis,
        no_target_umi_filter      = true,
        rps_limit                 = self.rps_limit,
        aligner                   = null,
        is_pd                     = false,
        reference_path            = self.reference_path,
        is_antibody_only          = SPATIAL_RNA_COUNTER_PREP.is_antibody_only,
        recovered_cells           = null,
        force_cells               = null,
        r1_length                 = self.r1_length,
        r2_length                 = self.r2_length,
        trim_polya_min_score      = self.trim_polya_min_score,
        trim_tso_min_score        = self.trim_tso_min_score,
        barcodes_under_tissue     = SPATIAL_IMAGING_CS.barcodes_under_tissue,
        alignment_metrics         = SPATIAL_IMAGING_CS.alignment_metrics,
        aligned_fiducials         = SPATIAL_IMAGING_CS.aligned_fiducials,
        tissue_hires_img          = SPATIAL_IMAGING_CS.tissue_hires_image,
        tissue_lowres_img         = SPATIAL_IMAGING_CS.tissue_lowres_image,
        detected_tissue_img       = SPATIAL_IMAGING_CS.detected_tissue_image,
        tissue_positions_list     = SPATIAL_IMAGING_CS.tissue_positions_list,
        image_scale_factors       = SPATIAL_IMAGING_CS.image_scalefactors,
        fraction_under_tissue     = SPATIAL_IMAGING_CS.fraction_under_tissue,
        feature_reference         = null,
    )

    call CLOUPE_TILE_IMAGES(
        tissue_image_paths    = self.tissue_image_paths,
        tile_size             = 512,
        skip_stage            = false,
        no_secondary_analysis = false,
    ) using (
        volatile = true,
    )

    call CLOUPE_PREPROCESS(
        pipestance_type              = "SPATIAL_RNA_COUNTER_CS",
        sample_id                    = self.sample_id,
        sample_desc                  = self.sample_desc,
        analysis                     = SPATIAL_RNA_COUNTER.analysis,
        filtered_gene_bc_matrices_h5 = SPATIAL_RNA_COUNTER.filtered_gene_bc_matrices_h5,
        metrics_json                 = SPATIAL_RNA_COUNTER.metrics_summary_json,
        aggregation_csv              = null,
        gem_group_index_json         = null,
        tissue_image_paths           = self.tissue_image_paths,
        dark_images                  = self.dark_images,
        tissue_positions_list        = SPATIAL_IMAGING_CS.tissue_positions_list,
        fiducial_positions_list      = SPATIAL_IMAGING_CS.fiducial_positions_list,
        dzi_info                     = CLOUPE_TILE_IMAGES.dzi_info,
        dzi_tiles_paths              = CLOUPE_TILE_IMAGES.dzi_tiles_paths,
        scale_factors_json           = SPATIAL_IMAGING_CS.image_scalefactors,
        no_secondary_analysis        = false,
        barcode_whitelist            = SPATIAL_RNA_COUNTER_PREP.barcode_whitelist,
        loupe_map                    = null,
        product_type                 = "sp",
    )

    return (
        possorted_genome_bam          = SPATIAL_RNA_COUNTER.possorted_genome_bam,
        possorted_genome_bam_index    = SPATIAL_RNA_COUNTER.possorted_genome_bam_index,
        web_summary                   = SPATIAL_RNA_COUNTER.web_summary,
        spatial                       = SPATIAL_RNA_COUNTER.spatial,
        metrics_summary               = SPATIAL_RNA_COUNTER.metrics_summary_csv,
        raw_feature_bc_matrix         = SPATIAL_RNA_COUNTER.raw_gene_bc_matrices_mex,
        raw_feature_bc_matrix_h5      = SPATIAL_RNA_COUNTER.raw_gene_bc_matrices_h5,
        filtered_feature_bc_matrix    = SPATIAL_RNA_COUNTER.filtered_gene_bc_matrices_mex,
        filtered_feature_bc_matrix_h5 = SPATIAL_RNA_COUNTER.filtered_gene_bc_matrices_h5,
        analysis                      = SPATIAL_RNA_COUNTER.analysis_csv,
        molecule_info                 = SPATIAL_RNA_COUNTER.molecule_info,
        cloupe                        = CLOUPE_PREPROCESS.output_for_cloupe,
        target_panel                  = SPATIAL_RNA_COUNTER.target_panel,
    )
}

#
# @include "__399-A1.mro"
#

call SPATIAL_RNA_COUNTER_CS(
    sample_id                 = "399-A1",
    sample_def                = [
        {
            "fastq_mode": "ILMN_BCL2FASTQ",
            "gem_group": null,
            "lanes": null,
            "library_type": "Gene Expression",
            "read_path": "/gpfs/data/yanailab/runs/2023-04-15",
            "sample_indices": ["any"],
            "sample_names": ["BS21014A"],
            "subsample_rate": null,
            "target_set": null,
            "target_set_name": null,
        },
    ],
    sample_desc               = "",
    slide_serial_capture_area = "V12D12-399-A1",
    loupe_alignment_file      = "/gpfs/home/jw7078/ST-399/V12D12-399-A1.json",
    gpr_file                  = null,
    reference_path            = "/gpfs/data/yanailab/refs/mus_musculus/refdata-gex-mm10-2020-A_JY",
    no_bam                    = false,
    no_secondary_analysis     = false,
    rps_limit                 = null,
    r1_length                 = null,
    r2_length                 = null,
    trim_polya_min_score      = 20,
    trim_tso_min_score        = 20,
    tissue_image_paths        = ["/gpfs/home/jw7078/ST-399/ST-399-A1.jpg"],
    dark_images               = 0,
    reorientation_mode        = null,
)
