@seqera/node-red-seqera
Version:
Node-RED nodes for interacting with the Seqera Platform API
293 lines (292 loc) • 13.5 kB
JSON
[
{
"id": "a8f9e2c3d1b45678",
"type": "tab",
"label": "RNA-seq to DifferentialAbundance",
"disabled": false,
"info": "# RNA-seq to Differential Abundance Pipeline\n\nThis workflow demonstrates a complete RNA-seq analysis pipeline that:\n\n1. Takes user inputs (CSV samplesheet, base path, contrasts)\n2. Launches nf-core/rnaseq with dynamic output directory\n3. Monitors the rnaseq pipeline until completion\n4. On success, automatically launches nf-core/differentialabundance\n5. Uses outputs from rnaseq as inputs to differentialabundance\n6. Monitors differentialabundance until completion\n\n## Setup Requirements\n\n### Seqera Configuration\n- All Seqera nodes need a Seqera configuration to be assigned\n- Ensure your token has Launch permissions\n\n### Launchpad Pipelines\n- Create a Launchpad entry for nf-core/rnaseq\n- Create a Launchpad entry for nf-core/differentialabundance\n- Both should be pre-configured with compute environments and basic settings\n\n### Input Files\nYou'll need to prepare:\n1. **RNA-seq samplesheet CSV** - see example in documentation\n2. **Contrasts CSV** - defines comparisons for differential analysis\n3. **GTF annotation file** - path to reference annotation\n4. **Base output path** - e.g., s3://my-bucket/results or /path/to/results\n\n## How It Works\n\n1. Click the inject node and configure the inputs in the \"Set user inputs\" node\n2. The \"Generate outdir\" function creates a unique output directory from CSV basename\n3. nf-core/rnaseq launches with the samplesheet and generated outdir\n4. Monitor node polls status every 15 seconds\n5. On success, \"Prepare differentialabundance\" constructs file paths from rnaseq outputs\n6. nf-core/differentialabundance launches with the prepared parameters\n7. Monitor node tracks completion\n8. Debug nodes show status at each stage",
"env": []
},
{
"id": "inject_trigger",
"type": "inject",
"z": "a8f9e2c3d1b45678",
"name": "Start Pipeline",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 120,
"y": 200,
"wires": [["set_user_inputs"]]
},
{
"id": "set_user_inputs",
"type": "function",
"z": "a8f9e2c3d1b45678",
"name": "Set user inputs",
"func": "// USER CONFIGURATION - Edit these values\n// This example uses nf-core test data that works out of the box\n\n// Path to RNA-seq samplesheet CSV\n// Using small test dataset from this repository\nmsg.rnaseqSamplesheet = \"https://raw.githubusercontent.com/seqeralabs/node-red-seqera/main/docs/examples/data/rnaseq-tests-datasets.csv\";\n\n// Base output path (will be combined with CSV basename)\n// IMPORTANT: Change this to your actual output location\nmsg.basePath = \"s3://PATH_TO_YOUR_BUCKET\";\n\n// Path to contrasts CSV for differential abundance\n// This defines comparisons: WT vs RAP1_UNINDUCED, WT vs RAP1_IAA_30M, etc.\nmsg.contrastsCSV = \"https://raw.githubusercontent.com/seqeralabs/node-red-seqera/main/docs/examples/data/rnaseq-test-contrasts.csv\";\n\n// Genome parameter (use iGenomes reference)\n// The test data is S. cerevisiae (yeast)\nmsg.genome = \"R64-1-1\";\n\n// Launchpad pipeline names (must exist in your workspace)\nmsg.rnaseqLaunchpad = \"nf-core-rnaseq\";\nmsg.diffabundLaunchpad = \"nf-core-differentialabundance\";\n\n// Additional RNA-seq parameters (optional)\nmsg.rnaseqExtraParams = {\n \"aligner\": \"star_salmon\",\n \"pseudo_aligner\": null\n};\n\n// Store CSV path for later\nmsg.csvPath = msg.rnaseqSamplesheet;\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 300,
"y": 200,
"wires": [["generate_outdir"]]
},
{
"id": "generate_outdir",
"type": "function",
"z": "a8f9e2c3d1b45678",
"name": "Generate outdir",
"func": "// Extract basename from CSV path\nconst csvPath = msg.rnaseqSamplesheet;\nconst pathParts = csvPath.split('/');\nconst csvFilename = pathParts[pathParts.length - 1];\nconst csvBasename = csvFilename.replace(/\\.csv$/i, '');\n\n// Remove trailing slash from base path if present\nconst basePath = msg.basePath.replace(/\\/$/, '');\n\n// Construct output directory\nmsg.outdir = `${basePath}/${csvBasename}`;\n\n// Store for later use\nmsg.rnaseqOutdir = msg.outdir;\n\nnode.status({fill: \"blue\", shape: \"dot\", text: `outdir: ${msg.outdir}`});\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 200,
"wires": [["launch_rnaseq"]]
},
{
"id": "launch_rnaseq",
"type": "seqera-workflow-launch",
"z": "a8f9e2c3d1b45678",
"name": "Launch nf-core/rnaseq",
"seqera": "37a74dee5cfd3aa6",
"launchpadName": "rnaseqLaunchpad",
"launchpadNameType": "msg",
"paramsKey": "{\t \"input\": msg.rnaseqSamplesheet,\t \"outdir\": msg.outdir,\t \"genome\": msg.genome,\t \"aligner\": msg.rnaseqExtraParams.aligner\t}",
"paramsKeyType": "jsonata",
"workspaceId": "",
"workspaceIdType": "str",
"sourceWorkspaceId": "",
"sourceWorkspaceIdType": "str",
"x": 700,
"y": 200,
"wires": [["monitor_rnaseq"]]
},
{
"id": "monitor_rnaseq",
"type": "seqera-workflow-monitor",
"z": "a8f9e2c3d1b45678",
"name": "Monitor nf-core/rnaseq",
"seqera": "37a74dee5cfd3aa6",
"workflowId": "workflowId",
"workflowIdType": "msg",
"workspaceId": "",
"workspaceIdType": "str",
"keepPolling": true,
"poll": "15",
"pollUnits": "seconds",
"x": 950,
"y": 200,
"wires": [["debug_rnaseq_running"], ["prepare_diffabund"], ["debug_rnaseq_failed"]]
},
{
"id": "prepare_diffabund",
"type": "function",
"z": "a8f9e2c3d1b45678",
"name": "Prepare differentialabundance inputs",
"func": "// Extract the outdir that was used for rnaseq\nconst rnaseqOutdir = msg.rnaseqOutdir;\n\n// Remove trailing slash if present\nconst baseOutdir = rnaseqOutdir.replace(/\\/$/, '');\n\n// Construct paths to rnaseq outputs based on standard nf-core/rnaseq structure\n// Assumes STAR+Salmon quantification (most common)\nconst matrixPath = `${baseOutdir}/star_salmon/salmon.merged.gene_counts.tsv`;\nconst lengthMatrixPath = `${baseOutdir}/star_salmon/salmon.merged.gene_lengths.tsv`;\n\n// Prepare parameters for differentialabundance\n// The samplesheet needs to have a 'group' column (which becomes 'condition' for differential analysis)\nmsg.diffabundParams = {\n \"input\": msg.rnaseqSamplesheet, // Reuse the same samplesheet (must have 'group' column)\n \"contrasts\": msg.contrastsCSV,\n \"matrix\": matrixPath,\n \"transcript_length_matrix\": lengthMatrixPath,\n \"genome\": msg.genome, // Use same genome as rnaseq\n \"study_name\": msg.rnaseqOutdir.split('/').pop(), // Use the basename as study name\n \"study_type\": \"rnaseq\",\n \"deseq2_vst_nsub\": 100, // Required to make test data work. Please set to a realistic value for real data!\n \"outdir\": `${baseOutdir}_differentialabundance`\n};\n\nnode.status({\n fill: \"green\", \n shape: \"dot\", \n text: \"RNA-seq complete, launching diffabund\"\n});\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 210,
"y": 320,
"wires": [["launch_diffabund"]]
},
{
"id": "launch_diffabund",
"type": "seqera-workflow-launch",
"z": "a8f9e2c3d1b45678",
"name": "Launch nf-core/differentialabundance",
"seqera": "37a74dee5cfd3aa6",
"launchpadName": "diffabundLaunchpad",
"launchpadNameType": "msg",
"paramsKey": "diffabundParams",
"paramsKeyType": "msg",
"workspaceId": "",
"workspaceIdType": "str",
"sourceWorkspaceId": "",
"sourceWorkspaceIdType": "str",
"x": 570,
"y": 320,
"wires": [["monitor_diffabund"]]
},
{
"id": "monitor_diffabund",
"type": "seqera-workflow-monitor",
"z": "a8f9e2c3d1b45678",
"name": "Monitor nf-core/differentialabundance",
"seqera": "37a74dee5cfd3aa6",
"workflowId": "workflowId",
"workflowIdType": "msg",
"workspaceId": "",
"workspaceIdType": "str",
"keepPolling": true,
"poll": "15",
"pollUnits": "seconds",
"x": 930,
"y": 320,
"wires": [["debug_diffabund_running"], ["debug_diffabund_success"], ["debug_diffabund_failed"]]
},
{
"id": "debug_diffabund_running",
"type": "debug",
"z": "a8f9e2c3d1b45678",
"name": "DiffAbund Running",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload.workflow.status",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1230,
"y": 280,
"wires": []
},
{
"id": "debug_diffabund_success",
"type": "debug",
"z": "a8f9e2c3d1b45678",
"name": "DiffAbund Complete",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1240,
"y": 320,
"wires": []
},
{
"id": "debug_diffabund_failed",
"type": "debug",
"z": "a8f9e2c3d1b45678",
"name": "DiffAbund Failed",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1230,
"y": 360,
"wires": []
},
{
"id": "comment_trigger",
"type": "comment",
"z": "a8f9e2c3d1b45678",
"name": "1. Start: Configure inputs",
"info": "Click the inject node to start the workflow.\n\nBefore running, open the \"Set user inputs\" function node\nand configure:\n- rnaseqSamplesheet: Path to your CSV file\n- basePath: Base output directory\n- contrastsCSV: Path to contrasts definition\n- gtfFile: Path to GTF annotation\n- rnaseqLaunchpad: Name of your rnaseq pipeline in Seqera\n- diffabundLaunchpad: Name of your differentialabundance pipeline",
"x": 140,
"y": 140,
"wires": []
},
{
"id": "comment_generate",
"type": "comment",
"z": "a8f9e2c3d1b45678",
"name": "2. Generate unique output directory",
"info": "This function extracts the CSV filename and creates\na unique output directory by combining:\n\nbasePath + CSV basename (without .csv extension)\n\nExample:\n- Input CSV: s3://bucket/data/experiment123.csv\n- Base path: s3://bucket/results\n- Output dir: s3://bucket/results/experiment123",
"x": 540,
"y": 140,
"wires": []
},
{
"id": "comment_rnaseq",
"type": "comment",
"z": "a8f9e2c3d1b45678",
"name": "3. Launch & Monitor RNA-seq",
"info": "Launches nf-core/rnaseq using the Launchpad configuration.\n\nParameters passed:\n- input: samplesheet CSV path\n- outdir: generated output directory\n- gtf: annotation file path\n- aligner: STAR+Salmon (default)\n\nThe monitor node polls every 15 seconds and has three outputs:\n- Port 1: Running status (continuous updates)\n- Port 2: Success (triggers next stage)\n- Port 3: Failed (goes to debug)",
"x": 940,
"y": 140,
"wires": []
},
{
"id": "comment_prepare",
"type": "comment",
"z": "a8f9e2c3d1b45678",
"name": "4. Prepare DifferentialAbundance",
"info": "Once RNA-seq succeeds, this function constructs the input\nparameters for nf-core/differentialabundance.\n\nIt builds file paths based on the known output structure:\n- matrix: star_salmon/salmon.merged.gene_counts.tsv\n- transcript_length_matrix: star_salmon/salmon.merged.gene_lengths.tsv\n\nReuses:\n- Same samplesheet (must include 'condition' column)\n- Same GTF file\n- Contrasts CSV for comparison definitions",
"x": 370,
"y": 380,
"wires": []
},
{
"id": "comment_diffabund",
"type": "comment",
"z": "a8f9e2c3d1b45678",
"name": "5. Launch & Monitor DifferentialAbundance",
"info": "Launches nf-core/differentialabundance with:\n- input: samplesheet with condition column\n- contrasts: comparison definitions\n- matrix: count matrix from RNA-seq\n- transcript_length_matrix: gene lengths from RNA-seq\n- gtf: same annotation used for RNA-seq\n- outdir: rnaseq_outdir + '_differentialabundance' suffix\n\nThe monitor node tracks completion and outputs to debug nodes.",
"x": 900,
"y": 380,
"wires": []
},
{
"id": "debug_rnaseq_failed",
"type": "debug",
"z": "a8f9e2c3d1b45678",
"name": "RNA-seq Failed",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1220,
"y": 220,
"wires": []
},
{
"id": "debug_rnaseq_running",
"type": "debug",
"z": "a8f9e2c3d1b45678",
"name": "RNA-seq Running",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload.workflow.status",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1230,
"y": 180,
"wires": []
},
{
"id": "37a74dee5cfd3aa6",
"type": "seqera-config",
"baseUrl": "https://api.cloud.seqera.io",
"workspaceId": "162690105070735"
},
{
"id": "fb143a03b9f7e8af",
"type": "global-config",
"env": [],
"modules": {
"@seqera/node-red-seqera": "1.0.1"
}
}
]