From 08a077683db5f01763814724071f22d7ab7d7e78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 18:58:15 +0000 Subject: [PATCH 01/10] Bump follow-redirects Bumps the npm_and_yarn group with 1 update in the /mcc directory: [follow-redirects](https://github.com/follow-redirects/follow-redirects). Updates `follow-redirects` from 1.15.11 to 1.16.0 - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.11...v1.16.0) --- updated-dependencies: - dependency-name: follow-redirects dependency-version: 1.16.0 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] --- mcc/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mcc/package-lock.json b/mcc/package-lock.json index 5dcd21515..93d63b611 100644 --- a/mcc/package-lock.json +++ b/mcc/package-lock.json @@ -5498,9 +5498,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "dev": true, "funding": [ { From 222ce6e1d83a9697d359b02e665729decd0c5f74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 02:26:11 +0000 Subject: [PATCH 02/10] Bump uuid in /mcc in the npm_and_yarn group across 1 directory Bumps the npm_and_yarn group with 1 update in the /mcc directory: [uuid](https://github.com/uuidjs/uuid). Updates `uuid` from 11.1.0 to 14.0.0 - [Release notes](https://github.com/uuidjs/uuid/releases) - [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md) - [Commits](https://github.com/uuidjs/uuid/compare/v11.1.0...v14.0.0) --- updated-dependencies: - dependency-name: uuid dependency-version: 14.0.0 dependency-type: direct:production dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] --- mcc/package-lock.json | 11 ++++++----- mcc/package.json | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/mcc/package-lock.json b/mcc/package-lock.json index 93d63b611..d31b6e54d 100644 --- a/mcc/package-lock.json +++ b/mcc/package-lock.json @@ -21,7 +21,7 @@ "react-dom": "^17.0.0", "react-tooltip": "^5.28.0", "tsv": "^0.2.0", - "uuid": "^11.1.0" + "uuid": "^14.0.0" }, "devDependencies": { "@labkey/build": "^9.1.0", @@ -9114,15 +9114,16 @@ } }, "node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz", + "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { - "uuid": "dist/esm/bin/uuid" + "uuid": "dist-node/bin/uuid" } }, "node_modules/vary": { diff --git a/mcc/package.json b/mcc/package.json index 37af629f1..49dc3078b 100644 --- a/mcc/package.json +++ b/mcc/package.json @@ -22,7 +22,7 @@ "react-dom": "^17.0.0", "react-tooltip": "^5.28.0", "tsv": "^0.2.0", - "uuid": "^11.1.0", + "uuid": "^14.0.0", "google-palette": "^1.1.1" }, "devDependencies": { From 86296910e421c5ca11c260c788957e4b67f81424 Mon Sep 17 00:00:00 2001 From: bbimber Date: Mon, 27 Apr 2026 13:30:39 -0700 Subject: [PATCH 03/10] Correct typo --- mcc/resources/web/mcc/panel/MccImportPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcc/resources/web/mcc/panel/MccImportPanel.js b/mcc/resources/web/mcc/panel/MccImportPanel.js index 797829bd9..8e8626c72 100644 --- a/mcc/resources/web/mcc/panel/MccImportPanel.js +++ b/mcc/resources/web/mcc/panel/MccImportPanel.js @@ -242,7 +242,7 @@ Ext4.define('MCC.panel.MccImportPanel', { }, damOrSire: function(val, panel, row) { - if (val && val.toUpperCase() === 'NA' || val.toUpperCase() === 'N/A') { + if (val && (val.toUpperCase() === 'NA' || val.toUpperCase() === 'N/A')) { val = null; } From 35bf26cabd77e9f01ad49b80729806302d53ff8f Mon Sep 17 00:00:00 2001 From: bbimber Date: Mon, 27 Apr 2026 14:20:31 -0700 Subject: [PATCH 04/10] Allow m/f for sex --- mcc/resources/web/mcc/panel/MccImportPanel.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mcc/resources/web/mcc/panel/MccImportPanel.js b/mcc/resources/web/mcc/panel/MccImportPanel.js index 8e8626c72..47373ecc7 100644 --- a/mcc/resources/web/mcc/panel/MccImportPanel.js +++ b/mcc/resources/web/mcc/panel/MccImportPanel.js @@ -275,9 +275,19 @@ Ext4.define('MCC.panel.MccImportPanel', { sex: function(val, panel, row) { val = panel.stripLeadingNumbers(val); - if (val && val.toLowerCase() === 'tbd') { + if (!val) { + return val; + } + + if (val.toLowerCase() === 'tbd') { val = 'unknown'; } + else if (val.toLowerCase() === 'm') { + val = 'male'; + } + else if (val.toLowerCase() === 'f') { + val = 'female'; + } val = panel.enforceAllowableValues(val, ['male', 'female', 'unknown'], row); From 282fadf6968c271078f7d23ac7f8df9babd22b8d Mon Sep 17 00:00:00 2001 From: bbimber Date: Fri, 8 May 2026 15:14:04 -0700 Subject: [PATCH 05/10] Update packages --- mcc/package-lock.json | 31 ++++++++++++++----------------- mcc/package.json | 2 +- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/mcc/package-lock.json b/mcc/package-lock.json index d31b6e54d..a385256ac 100644 --- a/mcc/package-lock.json +++ b/mcc/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", - "@labkey/api": "^1.39.0", + "@labkey/api": "^1.51.0", "@mui/material": "^5.0.0", "@mui/system": "^5.0.0", "@mui/x-data-grid": "^6.0.0", @@ -991,11 +991,10 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", - "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", + "version": "7.29.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz", + "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", @@ -2379,9 +2378,9 @@ "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" }, "node_modules/@labkey/api": { - "version": "1.39.0", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.39.0.tgz", - "integrity": "sha512-u9CcsRSb5IA0P6XodXIiejMfUQee7zflx3Wqgy60u1+X6InBtHs/rvjlfg3U1TdeyF4jtpmhK9W0ocNs8PbhIA==" + "version": "1.51.1", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.51.1.tgz", + "integrity": "sha512-RORsQpToUXkGsZMqMfqW+5d8g3r09s2Pojjz4z66hZR3nXw6K6U7xaXih/+96vFwbJ7BeqUsbv71+5dxX6Bmfg==" }, "node_modules/@labkey/build": { "version": "9.1.0", @@ -5359,9 +5358,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "dev": true, "funding": [ { @@ -5372,8 +5371,7 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ], - "license": "BSD-3-Clause" + ] }, "node_modules/fastest-levenshtein": { "version": "1.0.16", @@ -7371,9 +7369,9 @@ } }, "node_modules/postcss": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", - "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", "dev": true, "funding": [ { @@ -7389,7 +7387,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", diff --git a/mcc/package.json b/mcc/package.json index 49dc3078b..3cd35587c 100644 --- a/mcc/package.json +++ b/mcc/package.json @@ -12,7 +12,7 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", - "@labkey/api": "^1.39.0", + "@labkey/api": "^1.51.0", "@mui/material": "^5.0.0", "@mui/system": "^5.0.0", "@mui/x-data-grid": "^6.0.0", From 61b6c76f00b5d0f38745418a2131f28c445b6fda Mon Sep 17 00:00:00 2001 From: bbimber Date: Wed, 13 May 2026 14:11:55 -0700 Subject: [PATCH 06/10] Smarter resume in bismark --- .../primeseq/pipeline/BismarkWrapper.java | 78 ++++++++++++------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java b/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java index 1af365e1a..8b896de33 100644 --- a/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java +++ b/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java @@ -81,7 +81,7 @@ public BismarkWrapper(@Nullable Logger logger) public static class BismarkAlignmentStep extends AbstractAlignmentPipelineStep implements AlignmentStep { - public BismarkAlignmentStep(AlignmentStepProvider provider, PipelineContext ctx) + public BismarkAlignmentStep(AlignmentStepProvider provider, PipelineContext ctx) { super(provider, ctx, new BismarkWrapper(ctx.getLogger())); } @@ -112,8 +112,8 @@ public AlignmentOutput performAlignment(Readset rs, List inputFastqs1, @Nu try { - File convertedGenome = new File(existingIndexDir, CONVERTED_GENOME_NAME); - File localIndexDir = new File(outputDirectory, "genome"); + File convertedGenome = FileUtil.appendName(existingIndexDir, CONVERTED_GENOME_NAME); + File localIndexDir = FileUtil.appendName(outputDirectory, "genome"); if (localIndexDir.exists()) { FileUtils.deleteDirectory(localIndexDir); @@ -122,8 +122,8 @@ public AlignmentOutput performAlignment(Readset rs, List inputFastqs1, @Nu output.addIntermediateFile(localIndexDir); getPipelineCtx().getLogger().debug("adding Genome and FASTA symlinks"); - Path link1 = Files.createSymbolicLink(new File(localIndexDir, CONVERTED_GENOME_NAME).toPath(), convertedGenome.toPath()); - Path link2 = Files.createSymbolicLink(new File(localIndexDir, referenceGenome.getWorkingFastaFile().getName()).toPath(), referenceGenome.getWorkingFastaFile().toPath()); + Path link1 = Files.createSymbolicLink(FileUtil.appendName(localIndexDir, CONVERTED_GENOME_NAME).toPath(), convertedGenome.toPath()); + Path link2 = Files.createSymbolicLink(FileUtil.appendName(localIndexDir, referenceGenome.getWorkingFastaFile().getName()).toPath(), referenceGenome.getWorkingFastaFile().toPath()); //output.addIntermediateFile(link1.toFile()); //output.addIntermediateFile(link2.toFile()); @@ -173,9 +173,27 @@ public AlignmentOutput performAlignment(Readset rs, List inputFastqs1, @Nu } String outputBasename = SequenceAnalysisService.get().getUnzippedBaseName(inputFastq1.getName()) + "_bismark_bt2" + (inputFastq2 == null ? "" : "_pe"); - File bam = new File(outputDirectory, outputBasename + ".bam"); + File bam = FileUtil.appendName(outputDirectory, outputBasename + ".bam"); + File bamDone = new File(bam.getPath() + ".done"); + output.addIntermediateFile(bamDone); getWrapper().setWorkingDir(outputDirectory); - getWrapper().execute(args); + + if (!bamDone.exists()) + { + getWrapper().execute(args); + try + { + FileUtils.touch(bamDone); + } + catch (IOException e) + { + throw new PipelineJobException(e); + } + } + else + { + getPipelineCtx().getLogger().debug("Done file exists, skipping re-run of bismark"); + } if (!bam.exists()) { @@ -183,7 +201,7 @@ public AlignmentOutput performAlignment(Readset rs, List inputFastqs1, @Nu } output.addOutput(bam, AlignmentOutputImpl.BAM_ROLE); - File report = new File(outputDirectory, SequenceAnalysisService.get().getUnzippedBaseName(inputFastq1.getName()) + "_bismark_bt2_" + (inputFastq2 == null ? "SE" : "PE") + "_report.txt"); + File report = FileUtil.appendName(outputDirectory, SequenceAnalysisService.get().getUnzippedBaseName(inputFastq1.getName()) + "_bismark_bt2_" + (inputFastq2 == null ? "SE" : "PE") + "_report.txt"); output.addOutput(report, "Bismark Summary Report"); output.addSequenceOutput(report, rs.getName() + ": Bisulfite Conversion Stats", "Bismark Methylation Conversion Stats", rs.getRowId(), null, referenceGenome.getGenomeId(), null); output.addCommandsExecuted(getWrapper().getCommandsExecuted()); @@ -216,7 +234,7 @@ public IndexOutput createIndex(ReferenceGenome referenceGenome, File outputDir) IndexOutputImpl output = new IndexOutputImpl(referenceGenome); //always make sure FASTA is in analysis directory - File localFasta = new File(outputDir, referenceGenome.getWorkingFastaFile().getName()); + File localFasta = FileUtil.appendName(outputDir, referenceGenome.getWorkingFastaFile().getName()); File indexOutputDir = localFasta.getParentFile(); boolean hasCachedIndex = AlignerIndexUtil.hasCachedIndex(this.getPipelineCtx(), getIndexCachedDirName(getPipelineCtx().getJob()), referenceGenome); @@ -255,20 +273,20 @@ public IndexOutput createIndex(ReferenceGenome referenceGenome, File outputDir) args.add(indexOutputDir.getPath()); getWrapper().execute(args); - File genomeBuild = new File(indexOutputDir, CONVERTED_GENOME_NAME); - File bowtie2TestFile = new File(genomeBuild, "CT_conversion/BS_CT.1.bt2"); + File genomeBuild = FileUtil.appendName(indexOutputDir, CONVERTED_GENOME_NAME); + File bowtie2TestFile = FileUtil.appendPath(genomeBuild, org.labkey.api.util.Path.parse("CT_conversion/BS_CT.1.bt2")); if (!bowtie2TestFile.exists()) { throw new PipelineJobException("Unable to find file, expected: " + bowtie2TestFile.getPath()); } - File indexBaseDir = new File(localFasta.getParentFile(), getIndexCachedDirName(getPipelineCtx().getJob())); + File indexBaseDir = FileUtil.appendName(localFasta.getParentFile(), getIndexCachedDirName(getPipelineCtx().getJob())); if (!indexBaseDir.exists()) { indexBaseDir.mkdirs(); } - File movedDir = new File(indexBaseDir, genomeBuild.getName()); + File movedDir = FileUtil.appendName(indexBaseDir, genomeBuild.getName()); try { FileUtils.moveDirectory(genomeBuild, movedDir); @@ -335,7 +353,7 @@ public Output performAnalysisPerSampleRemote(Readset rs, File inputBam, Referenc File queryNameSortBam; if (SequencePipelineService.get().getBamSortOrder(inputBam) != SAMFileHeader.SortOrder.queryname) { - queryNameSortBam = new SamSorter(getPipelineCtx().getLogger()).execute(inputBam, new File(outputDir, basename + ".querySort.bam"), SAMFileHeader.SortOrder.queryname); + queryNameSortBam = new SamSorter(getPipelineCtx().getLogger()).execute(inputBam, FileUtil.appendName(outputDir, basename + ".querySort.bam"), SAMFileHeader.SortOrder.queryname); outputBasename = FileUtil.getBaseName(queryNameSortBam); output.addIntermediateFile(queryNameSortBam); @@ -389,11 +407,15 @@ else if (!rs.hasPairedData()) getWrapper().setWorkingDir(outputDir); getWrapper().execute(args); + // TODO: optional Dedupe: + // samtools sort -n + // deduplicate_bismark [options] filename(s) + //add outputs getWrapper().getLogger().debug("using basename: " + outputBasename); - output.addOutput(new File(outputDir, outputBasename + ".M-bias.txt"), "Bismark M-Bias Report"); + output.addOutput(FileUtil.appendName(outputDir, outputBasename + ".M-bias.txt"), "Bismark M-Bias Report"); - File graph1 = new File(outputDir, outputBasename + ".M-bias_R1.png"); + File graph1 = FileUtil.appendName(outputDir, outputBasename + ".M-bias_R1.png"); if (graph1.exists()) { output.addOutput(graph1, "Bismark M-Bias Image"); @@ -403,7 +425,7 @@ else if (!rs.hasPairedData()) getPipelineCtx().getLogger().warn("file not found: " + graph1.getPath()); } - File graph2 = new File(outputDir, outputBasename + ".M-bias_R2.png"); + File graph2 = FileUtil.appendName(outputDir, outputBasename + ".M-bias_R2.png"); if (graph2.exists()) { output.addOutput(graph2, "Bismark M-Bias Image"); @@ -413,7 +435,7 @@ else if (!rs.hasPairedData()) getPipelineCtx().getLogger().warn("file not found: " + graph2.getPath()); } - output.addOutput(new File(outputDir, outputBasename + ".bam_splitting_report.txt"), "Bismark Splitting Report"); + output.addOutput(FileUtil.appendName(outputDir, outputBasename + ".bam_splitting_report.txt"), "Bismark Splitting Report"); //NOTE: because the data are likely directional, we will not encounter CTOB // OT – original top strand @@ -421,17 +443,17 @@ else if (!rs.hasPairedData()) // OB – original bottom strand // CTOB – complementary to original bottom strand List> CpGmethlyationData = Arrays.asList( - Pair.of(new File(outputDir, "CpG_OT_" + outputBasename + ".txt.gz"), 0), - Pair.of(new File(outputDir, "CpG_CTOT_" + outputBasename + ".txt.gz"), 0), - Pair.of(new File(outputDir, "CpG_OB_" + outputBasename + ".txt.gz"), -1), - Pair.of(new File(outputDir, "CpG_CTOB_" + outputBasename + ".txt.gz"), -1) + Pair.of(FileUtil.appendName(outputDir, "CpG_OT_" + outputBasename + ".txt.gz"), 0), + Pair.of(FileUtil.appendName(outputDir, "CpG_CTOT_" + outputBasename + ".txt.gz"), 0), + Pair.of(FileUtil.appendName(outputDir, "CpG_OB_" + outputBasename + ".txt.gz"), -1), + Pair.of(FileUtil.appendName(outputDir, "CpG_CTOB_" + outputBasename + ".txt.gz"), -1) ); List> NonCpGmethlyationData = Arrays.asList( - Pair.of(new File(outputDir, "NonCpG_OT_" + outputBasename + ".txt.gz"), 0), - Pair.of(new File(outputDir, "NonCpG_CTOT_" + outputBasename + ".txt.gz"), 0), - Pair.of(new File(outputDir, "NonCpG_OB_" + outputBasename + ".txt.gz"), -1), - Pair.of(new File(outputDir, "NonCpG_CTOB_" + outputBasename + ".txt.gz"), -1) + Pair.of(FileUtil.appendName(outputDir, "NonCpG_OT_" + outputBasename + ".txt.gz"), 0), + Pair.of(FileUtil.appendName(outputDir, "NonCpG_CTOT_" + outputBasename + ".txt.gz"), 0), + Pair.of(FileUtil.appendName(outputDir, "NonCpG_OB_" + outputBasename + ".txt.gz"), -1), + Pair.of(FileUtil.appendName(outputDir, "NonCpG_CTOB_" + outputBasename + ".txt.gz"), -1) ); if (getProvider().getParameterByName("mbias_only") != null && getProvider().getParameterByName("mbias_only").extractValue(getPipelineCtx().getJob(), getProvider(), getStepIdx(), Boolean.class, false)) @@ -443,8 +465,8 @@ else if (getProvider().getParameterByName("siteReport") != null && getProvider() getPipelineCtx().getLogger().info("creating per-site summary report"); Integer minCoverageDepth = getProvider().getParameterByName("minCoverageDepth").extractValue(getPipelineCtx().getJob(), getProvider(), getStepIdx(), Integer.class); - File siteReport = new File(outputDir, basename + ".CpG_Site_Summary.methylation.txt"); - File outputGff = new File(outputDir, basename + ".CpG_Site_Summary.gff"); + File siteReport = FileUtil.appendName(outputDir, basename + ".CpG_Site_Summary.methylation.txt"); + File outputGff = FileUtil.appendName(outputDir, basename + ".CpG_Site_Summary.gff"); produceSiteReport(getWrapper().getLogger(), siteReport, outputGff, CpGmethlyationData, minCoverageDepth); if (siteReport.exists()) From 45f314f1f832990743f2daba968ae721a555fd0d Mon Sep 17 00:00:00 2001 From: bbimber Date: Wed, 13 May 2026 15:01:29 -0700 Subject: [PATCH 07/10] Support deduplicate for bismark --- .../primeseq/pipeline/BismarkWrapper.java | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java b/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java index 8b896de33..9707371cb 100644 --- a/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java +++ b/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java @@ -79,6 +79,11 @@ public BismarkWrapper(@Nullable Logger logger) super(logger); } + protected File getDeduplicateExe() + { + return SequencePipelineService.get().getExeForPackage("BISMARKPATH", "deduplicate_bismark"); + } + public static class BismarkAlignmentStep extends AbstractAlignmentPipelineStep implements AlignmentStep { public BismarkAlignmentStep(AlignmentStepProvider provider, PipelineContext ctx) @@ -200,6 +205,35 @@ public AlignmentOutput performAlignment(Readset rs, List inputFastqs1, @Nu throw new PipelineJobException("Unable to find BAM: " + bam.getPath()); } + boolean deduplicate = getProvider().getParameterByName("deduplicate").extractValue(getPipelineCtx().getJob(), getProvider(), getStepIdx(), Boolean.class, false); + if (deduplicate) + { + File dedupBam = FileUtil.appendName(outputDirectory, outputBasename + ".deduplicated.bam"); + + List dedupArgs = new ArrayList<>(Arrays.asList( + getWrapper().getDeduplicateExe().getPath(), + "--bam", + "-o", + dedupBam.getPath() + )); + + if (inputFastq2 != null) + { + dedupArgs.add("--paired"); + } + + dedupArgs.add(bam.getPath()); + + getWrapper().execute(dedupArgs); + if (!dedupBam.exists()) + { + throw new PipelineJobException("Missing file: " + dedupBam.getPath()); + } + + output.addIntermediateFile(bam); + bam = dedupBam; + } + output.addOutput(bam, AlignmentOutputImpl.BAM_ROLE); File report = FileUtil.appendName(outputDirectory, SequenceAnalysisService.get().getUnzippedBaseName(inputFastq1.getName()) + "_bismark_bt2_" + (inputFastq2 == null ? "SE" : "PE") + "_report.txt"); output.addOutput(report, "Bismark Summary Report"); @@ -323,6 +357,9 @@ public Provider() }}, false), ToolParameterDescriptor.createCommandLineParam(CommandLineParam.createSwitch("--non_directional"), "non_directional", "Non-Directional", "The sequencing library was constructed in a non strand-specific manner, alignments to all four bisulfite strands will be reported", "checkbox", new JSONObject(){{ + }}, false), + ToolParameterDescriptor.create("deduplicate", "Run deduplicate", "If true, deduplicate_bismark will be run on the BAM", "checkbox", new JSONObject(){{ + }}, false) ), null, "http://www.bioinformatics.babraham.ac.uk/projects/bismark/", true, false); } @@ -407,10 +444,6 @@ else if (!rs.hasPairedData()) getWrapper().setWorkingDir(outputDir); getWrapper().execute(args); - // TODO: optional Dedupe: - // samtools sort -n - // deduplicate_bismark [options] filename(s) - //add outputs getWrapper().getLogger().debug("using basename: " + outputBasename); output.addOutput(FileUtil.appendName(outputDir, outputBasename + ".M-bias.txt"), "Bismark M-Bias Report"); From a9ffea71ca1c1f6767053e175f4813124126378c Mon Sep 17 00:00:00 2001 From: bbimber Date: Thu, 14 May 2026 09:46:36 -0700 Subject: [PATCH 08/10] Support deduplicate for bismark --- primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java b/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java index 9707371cb..07c30a23e 100644 --- a/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java +++ b/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java @@ -212,9 +212,7 @@ public AlignmentOutput performAlignment(Readset rs, List inputFastqs1, @Nu List dedupArgs = new ArrayList<>(Arrays.asList( getWrapper().getDeduplicateExe().getPath(), - "--bam", - "-o", - dedupBam.getPath() + "--bam" )); if (inputFastq2 != null) From 569057066ce036921d9cdd90de3ffb0382283dc6 Mon Sep 17 00:00:00 2001 From: bbimber Date: Fri, 15 May 2026 09:10:11 -0700 Subject: [PATCH 09/10] Presort BAM for deduplicate in bismark --- .../primeseq/pipeline/BismarkWrapper.java | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java b/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java index 07c30a23e..bd280ca6d 100644 --- a/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java +++ b/primeseq/src/org/labkey/primeseq/pipeline/BismarkWrapper.java @@ -1,6 +1,7 @@ package org.labkey.primeseq.pipeline; import htsjdk.samtools.SAMFileHeader; +import htsjdk.samtools.util.SequenceUtil; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; @@ -208,28 +209,45 @@ public AlignmentOutput performAlignment(Readset rs, List inputFastqs1, @Nu boolean deduplicate = getProvider().getParameterByName("deduplicate").extractValue(getPipelineCtx().getJob(), getProvider(), getStepIdx(), Boolean.class, false); if (deduplicate) { - File dedupBam = FileUtil.appendName(outputDirectory, outputBasename + ".deduplicated.bam"); + try + { + File queryNameSortBam = FileUtil.appendName(bam.getParentFile(), basename + ".querySort.bam"); + if (SequencePipelineService.get().getBamSortOrder(bam) != SAMFileHeader.SortOrder.queryname) + { + queryNameSortBam = new SamSorter(getPipelineCtx().getLogger()).execute(bam, queryNameSortBam, SAMFileHeader.SortOrder.queryname); + output.addIntermediateFile(queryNameSortBam); + } + else + { + queryNameSortBam = bam; + } - List dedupArgs = new ArrayList<>(Arrays.asList( - getWrapper().getDeduplicateExe().getPath(), - "--bam" - )); + File dedupBam = FileUtil.appendName(outputDirectory, FileUtil.getBaseName(queryNameSortBam) + ".deduplicated.bam"); + List dedupArgs = new ArrayList<>(Arrays.asList( + getWrapper().getDeduplicateExe().getPath(), + "--bam" + )); - if (inputFastq2 != null) - { - dedupArgs.add("--paired"); - } + if (inputFastq2 != null) + { + dedupArgs.add("--paired"); + } + + dedupArgs.add(queryNameSortBam.getPath()); - dedupArgs.add(bam.getPath()); + getWrapper().execute(dedupArgs); + if (!dedupBam.exists()) + { + throw new PipelineJobException("Missing file: " + dedupBam.getPath()); + } - getWrapper().execute(dedupArgs); - if (!dedupBam.exists()) + output.addIntermediateFile(bam); + bam = dedupBam; + } + catch (IOException e) { - throw new PipelineJobException("Missing file: " + dedupBam.getPath()); + throw new PipelineJobException(e); } - - output.addIntermediateFile(bam); - bam = dedupBam; } output.addOutput(bam, AlignmentOutputImpl.BAM_ROLE); From de923ac5d9cee0c008011c24ce200bf5c4f3bb51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 11:10:39 +0000 Subject: [PATCH 10/10] Bump webpack-dev-server Bumps the npm_and_yarn group with 1 update in the /mcc directory: [webpack-dev-server](https://github.com/webpack/webpack-dev-server). Updates `webpack-dev-server` from 5.2.3 to 5.2.4 - [Release notes](https://github.com/webpack/webpack-dev-server/releases) - [Changelog](https://github.com/webpack/webpack-dev-server/blob/main/CHANGELOG.md) - [Commits](https://github.com/webpack/webpack-dev-server/compare/v5.2.3...v5.2.4) --- updated-dependencies: - dependency-name: webpack-dev-server dependency-version: 5.2.4 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] --- mcc/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mcc/package-lock.json b/mcc/package-lock.json index a385256ac..82377ff88 100644 --- a/mcc/package-lock.json +++ b/mcc/package-lock.json @@ -9403,9 +9403,9 @@ } }, "node_modules/webpack-dev-server": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.3.tgz", - "integrity": "sha512-9Gyu2F7+bg4Vv+pjbovuYDhHX+mqdqITykfzdM9UyKqKHlsE5aAjRhR+oOEfXW5vBeu8tarzlJFIZva4ZjAdrQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.4.tgz", + "integrity": "sha512-GqDPGZN9bRqKBTkp4aWkobDDHMsrXKoGSdOH56smIri8qR0JG8gfL8/v/f/OZR3/OKXjG8uwJbFVhKm/FNU/UA==", "dev": true, "license": "MIT", "dependencies": {