diff --git a/tcrdb/resources/external/scRNAseq/Seurat3.rmd b/tcrdb/resources/external/scRNAseq/Seurat3.rmd
index a3911a6c7..9fb58d5aa 100644
--- a/tcrdb/resources/external/scRNAseq/Seurat3.rmd
+++ b/tcrdb/resources/external/scRNAseq/Seurat3.rmd
@@ -1,13 +1,16 @@
---
title: 'Seurat scRNA-seq Analysis'
+output: html_document
+
---
```{r Setup}
-knitr::opts_chunk$set(message=FALSE, warning=FALSE,echo=TRUE,error = FALSE)
library(knitr)
library(OOSAP)
+knitr::opts_chunk$set(message=FALSE, warning=FALSE, echo=TRUE, error = TRUE)
+
cores <- Sys.getenv('SEQUENCEANALYSIS_MAX_THREADS')
if (cores != ''){
print(paste0('Setting future::plan to ', cores, ' cores'))
diff --git a/tcrdb/resources/web/tcrdb/panel/LibraryExportPanel.js b/tcrdb/resources/web/tcrdb/panel/LibraryExportPanel.js
index 4988c82e5..e3d3b9934 100644
--- a/tcrdb/resources/web/tcrdb/panel/LibraryExportPanel.js
+++ b/tcrdb/resources/web/tcrdb/panel/LibraryExportPanel.js
@@ -88,7 +88,7 @@ Ext4.define('TCRdb.panel.LibraryExportPanel', {
border: false
},
items: [{
- html: 'Add an ordered list of plates, using tab-delimited columns. The first column(s) are plate ID and library type (GEX, VDJ, CITE, or HTO). These can either be one column (i.e. G234-1, C234-1, H234-1, or T234-1), or as two columns (234-1 GEX or 234-1 HTO). An optional next column is the lane assignment (i.e. Novaseq1, HiSeq1, HiSeq2). Finally, an optional final column can be used to provide the alias for this pool. This is mostly used for CITE-Seq/HTOs, where multiple libraries are pre-pooled. See these examples:
' +
+ html: 'Add an ordered list of plates, using tab-delimited columns. The first column(s) are plate ID and library type (GEX, VDJ, CITE, or HTO). These can either be one column (i.e. G234-1, C234-1, H234-1, or T234-1), or as two columns (234-1 GEX or 234-1 HTO). An optional next column is the lane assignment (i.e. Novaseq1, HiSeq1, HiSeq2). Finally, an optional final column can be used to provide the alias for this pool. This is mostly used for CITE-Seq/HTOs, where multiple libraries are pre-pooled. Note, a wildcard can be used to specify all plates beginning with that prefix. See these examples:
' +
'
' +
'234-2\tGEX
' +
'234-2\tVDJ
' +
@@ -101,6 +101,7 @@ Ext4.define('TCRdb.panel.LibraryExportPanel', {
'235-2\tHTO\tHiSeq2\tBNB-HTO-1
' +
'H235-2\tHiSeq1\tBNB-HTO-1
' +
'C235-2\tHiSeq1\tBNB-HTO-1' +
+ 'C235-*\tHiSeq2\tBNB-HTO-2' +
'',
border: false
},{
@@ -171,6 +172,7 @@ Ext4.define('TCRdb.panel.LibraryExportPanel', {
}, this);
var hadError = false;
+ var wildcards = {};
Ext4.Array.forEach(text, function(r){
if (r.length < 2){
hadError = true;
@@ -186,6 +188,12 @@ Ext4.define('TCRdb.panel.LibraryExportPanel', {
Ext4.Array.forEach(r, function(val, idx){
r[idx] = Ext4.String.trim(val);
}, this);
+
+ if (r[0].match('\\*$')) {
+ var m = r[0].match('\\*$');
+ var val = r[0].substr(0, m.index);
+ wildcards[val] = r;
+ }
}, this);
if (hadError) {
@@ -193,7 +201,58 @@ Ext4.define('TCRdb.panel.LibraryExportPanel', {
return;
}
- this.onSubmit(btn, text);
+ if (!Ext4.Object.isEmpty(wildcards)) {
+ LABKEY.Query.selectRows({
+ method: 'POST',
+ containerPath: Laboratory.Utils.getQueryContainerPath(),
+ schemaName: 'tcrdb',
+ queryName: 'cdnas',
+ columns: 'rowid,plateId',
+ filterArray: [LABKEY.Filter.create('plateId', Ext4.Object.getKeys(wildcards).join(';'), LABKEY.Filter.Types.CONTAINS_ONE_OF)],
+ scope: this,
+ failure: LDK.Utils.getErrorCallback(),
+ success: function (results) {
+ if (results.rows.length) {
+ var prefixToPlate = {};
+ Ext4.Array.forEach(results.rows, function (row) {
+ Ext4.Array.forEach(Ext4.Object.getKeys(wildcards), function (prefix) {
+ if (row.plateId && row.plateId.includes(prefix)) {
+ prefix = prefix + '*';
+ prefixToPlate[prefix] = prefixToPlate[prefix] || [];
+ prefixToPlate[prefix].push(row.plateId);
+ }
+ }, this);
+ }, this);
+
+ Ext4.Array.forEach(Ext4.Object.getKeys(prefixToPlate), function (prefix) {
+ prefixToPlate[prefix] = Ext4.unique(prefixToPlate[prefix]);
+ }, this);
+
+ var updatedText = [];
+ var prefixes = Ext4.Object.getKeys(prefixToPlate);
+ Ext4.Array.forEach(text, function (r, idx) {
+ var plateId = r[0];
+ if (prefixes.indexOf(plateId) == -1) {
+ updatedText.push(r);
+ }
+ else {
+ Ext4.Array.forEach(prefixToPlate[plateId], function(newPlate){
+ var r2 = [].concat(r);
+ r2[0] = newPlate;
+ updatedText.push(r2);
+ }, this);
+ }
+ }, this);
+
+ text = updatedText;
+ }
+
+ this.onSubmit(btn, text);
+ }
+ });
+ } else {
+ this.onSubmit(btn, text);
+ }
}
}]
});
@@ -265,11 +324,11 @@ Ext4.define('TCRdb.panel.LibraryExportPanel', {
var instrument = btn.up('tcrdb-libraryexportpanel').down('#instrument').getValue();
var plateId = btn.up('tcrdb-libraryexportpanel').down('#sourcePlates').getValue();
var delim = 'TAB';
- var extention = 'txt';
+ var extension = 'txt';
var split = '\t';
if (instrument !== 'NextSeq (MPSSR)') {
delim = 'COMMA';
- extention = 'csv';
+ extension = 'csv';
split = ',';
}
@@ -277,7 +336,7 @@ Ext4.define('TCRdb.panel.LibraryExportPanel', {
var rows = LDK.Utils.CSVToArray(Ext4.String.trim(val), split);
LABKEY.Utils.convertToTable({
- fileName: plateId + '.' + extention,
+ fileName: plateId + '.' + extension,
rows: rows,
delim: delim
});
@@ -757,10 +816,10 @@ Ext4.define('TCRdb.panel.LibraryExportPanel', {
var delim = instrument === 'Novogene' ? '\t' : ',';
Ext4.Array.forEach(sortedRows, function (r) {
- processType(readsetIds, rows, r, 'readsetId', 'GEX', 500, 1, 'G', null, false);
- processType(readsetIds, rows, r, 'enrichedReadsetId', 'TCR', 700, 1, 'T', null, false);
- processType(readsetIds, rows, r, 'hashingReadsetId', 'HTO', 182, 5, 'H', 'Cell hashing, 190bp amplicon. Please QC individually and pool in equal amounts per lane', true);
- processType(readsetIds, rows, r, 'citeseqReadsetId', 'CITE', 182, 5, 'C', 'CITE-Seq, 190bp amplicon. Please QC individually and pool in equal amounts per lane', false);
+ processType(readsetIds, rows, r, 'readsetId', 'GEX', 500, 0.01, 'G', null, false);
+ processType(readsetIds, rows, r, 'enrichedReadsetId', 'TCR', 700, 0.01, 'T', null, false);
+ processType(readsetIds, rows, r, 'hashingReadsetId', 'HTO', 182, 0.05, 'H', 'Cell hashing, 190bp amplicon. Please QC individually and pool in equal amounts per lane', true);
+ processType(readsetIds, rows, r, 'citeseqReadsetId', 'CITE', 182, 0.05, 'C', 'CITE-Seq, 190bp amplicon. Please QC individually and pool in equal amounts per lane', false);
}, this);
//add missing barcodes:
diff --git a/tcrdb/src/org/labkey/tcrdb/pipeline/CellRangerCellHashingHandler.java b/tcrdb/src/org/labkey/tcrdb/pipeline/CellRangerCellHashingHandler.java
index 00be83f8c..3cd2ecf90 100644
--- a/tcrdb/src/org/labkey/tcrdb/pipeline/CellRangerCellHashingHandler.java
+++ b/tcrdb/src/org/labkey/tcrdb/pipeline/CellRangerCellHashingHandler.java
@@ -63,7 +63,7 @@ public static List