UNPKG

@seqera/node-red-seqera

Version:

Node-RED nodes for interacting with the Seqera Platform API

293 lines (292 loc) 13.5 kB
[ { "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" } } ]