@@ -498,6 +527,7 @@
import ResearchBarPlotV2 from "@/components/researchPortal/ResearchBarPlotV2.vue";
import ResearchDotPlot from "@/components/researchPortal/ResearchDotPlot.vue";
import ResearchViolinPlot from "@/components/researchPortal/ResearchViolinPlot.vue";
+ import ResearchSingleCellSelector from "@/components/researchPortal/ResearchSingleCellSelector.vue";
const colors = ["#007bff","#048845","#8490C8","#BF61A5","#EE3124","#FCD700","#5555FF","#7aaa1c","#F88084","#9F78AC","#F5A4C7","#CEE6C1","#cccc00","#6FC7B6","#D5A768","#d4d4d4"]
@@ -506,7 +536,8 @@
ResearchUmapPlot,
ResearchBarPlotV2,
ResearchDotPlot,
- ResearchViolinPlot
+ ResearchViolinPlot,
+ ResearchSingleCellSelector
},
props: {
sectionId: {
@@ -586,7 +617,6 @@
segmentByCounts: null,
datasetId: null,
- datasetName: null,
cellTypeField: null,
geneNames: [],
@@ -595,7 +625,6 @@
dataLoaded: false,
preloadItem: '',
- tissueDisplay: '',
highlightHoverTimeout: null,
selectedTabs: {"a":"1", "b":"2"},
@@ -637,23 +666,48 @@
if(data.id===this.sectionId){
console.log(this.sectionId, 'Received on-select event:', data);
this.datasetId = data.value;
+ if(this.renderConfig["parameters"]?.datasetId){
+ keyParams.set({[this.renderConfig["parameters"]?.datasetId] : this.datasetId});
+ }
this.init();
}
},
- async init(){
- /*
- if(this.data.length !== 1){
- if(this.datasetData) {
- console.log('--->', this.datasetData);
- }else{
- console.log("please select a dataset");
- return;
+ clean(){
+ this.expressionStats = [];
+ this.cellCompositionVars = {
+ "a": {
+ umapColors: null,
+ colorByLabel: null,
+ highlightLabel: '',
+ highlightLabels: [],
+ cellTypeInfo: null
+ },
+ "b": {
+ umapColors: null,
+ colorByLabel: null,
+ highlightLabel: '',
+ highlightLabels: [],
+ cellTypeInfo: null
+ }
+ },
+ this.geneExpressionVars = {
+ "a": {
+ umapGeneColors: null,
+ selectedGene: null,
+ expressionStats: [],
+ selectedLabel: null,
+ },
+ "b": {
+ umapGeneColors: null,
+ selectedGene: null,
+ expressionStats: [],
+ selectedLabel: null,
}
- }else{
- this.datasetId = this.data[0].datasetId;
}
- */
-
+ },
+ async init(){
+ //check which components to enable based on cofig options
+ //all are enabled by default
this.componentsConfig = this.renderConfig["components"];
this.showCellInfo = this.componentsConfig?.["cell info"]?.enabled ?? true;
this.showCellProportion = this.componentsConfig?.["cell proportion"]?.enabled ?? true;
@@ -662,25 +716,38 @@
this.presetsConfig = this.renderConfig["presets"];
- //if user has not selected a dataset from the list
+ //check for datasetId
+ /* it can come from multiple places
+ 1. 'on-select' event from byor
+ 2. query string param
+ 3. config preset
+ */
if(!this.datasetId || this.datasetId === ''){
- if(this.presetsConfig?.datasetId){
+ if(keyParams[this.renderConfig["parameters"]?.datasetId]){
+ this.datasetId = keyParams[this.renderConfig["parameters"].datasetId];
+ }else if(this.presetsConfig?.datasetId){
this.datasetId = this.presetsConfig.datasetId
}else{
console.log('select a dataset');
return;
}
}
-
- console.log(`loading dataset: ${this.datasetData.datasetId}`);
- console.log(' data', this.datasetData);
- this.tissueDisplay = this.datasetData["Tissue"];
- this.datasetName = this.datasetData["Name"];
- this.cellTypeField = this.presetsConfig?.["cell type label"];
- console.log("cellTypeField", this.cellTypeField, this.presetsConfig);
- this.cellCompositionVars['a'].colorByLabel = this.cellTypeField;
+ console.log(`requested dataset: ${this.datasetId}`);
+
+ //make sure it exists in the metadata
+ if(!this.data.find(x => x.datasetId === this.datasetId)){
+ console.log('dataset', this.datasetId, 'not in collection');
+ this.datasetId = null;
+ return;
+ }
+ console.log(' data', this.datasetData);
+
+ //clear existing data
+ this.clean();
+
+ //fetch base data
this.dataLoaded = false;
this.preloadItem = 'fields';
this.rawData = await this.fetchFields();
@@ -697,10 +764,18 @@
//pre-calculate colors for fields in each category
this.labelColors = this.calcLabelColors(this.rawData);
+
this.colorScalePlasmaColorsArray = d3.range(0, 1.01, 0.1).map(t => this.colorScalePlasma(t)).join(', ');
this.getColorByOptions();
+ //which label designates cell types
+ this.cellTypeField = this.presetsConfig?.["cell type label"];
+
+ console.log("cellTypeField", this.cellTypeField, this.presetsConfig);
+
+ this.cellCompositionVars['a'].colorByLabel = this.cellTypeField;
+
this.selectColorBy(this.cellTypeField, 'a');
this.selectColorBy(this.cellTypeField, 'b');
@@ -721,17 +796,17 @@
console.log('cell proportion component disabled')
}
- this.expressionStats = [];
-
-
- if(keyParams.gene){
- this.fetchGeneExpression(keyParams.gene.toUpperCase());
+ //load gene data from parameters
+ if(this.renderConfig["parameters"]?.gene){
+ if(keyParams[this.renderConfig["parameters"].gene]){
+ this.fetchGeneExpression(keyParams.gene.toUpperCase());
+ }
}
-
+ //load gene data from config
if(this.presetsConfig?.["genes"]){
this.presetsConfig["genes"].forEach(async (gene) => {
- await this.fetchGeneExpression(gene.toUpperCase());
+ this.fetchGeneExpression(gene.toUpperCase());
})
}
@@ -748,22 +823,10 @@
this.colorByOptions = colorByOptions2;
},
- updateDataUrl(url, paramaters){
- let updatedUrl = url;
- //tmp
- //updatedUrl = updatedUrl.replace(`$datasetId`, this.datasetData['Tissue'].toLowerCase());
-
- //use below once metadata is fixed
- paramaters.forEach(param => {
- if(param !== 'gene')
- updatedUrl = updatedUrl.replace(`$${param}`, this.datasetData[param]); //.toLowerCase().replaceAll(" ", "_")
- })
- return updatedUrl;
- },
async fetchFields() {
console.log('getting fields');
const fieldsDataPoint = this.renderConfig["data points"].find(x => x.role === "fields");
- const fieldsUrl = this.updateDataUrl(fieldsDataPoint.url, fieldsDataPoint.parameters);
+ const fieldsUrl = fieldsDataPoint.url.replace('$datasetId', this.datasetId);
try {
const response = await fetch(fieldsUrl);
const rawData = await response.json();
@@ -777,7 +840,7 @@
async fetchCoordinates() {
console.log('getting coordinates');
const coordinatesDataPoint = this.renderConfig["data points"].find(x => x.role === "coordinates");
- const coordinatesUrl = this.updateDataUrl(coordinatesDataPoint.url, coordinatesDataPoint.parameters);
+ const coordinatesUrl = coordinatesDataPoint.url.replace('$datasetId', this.datasetId);
try {
const response = await fetch(coordinatesUrl);
const json = this.utils.dataConvert.tsv2Json(await response.text());
@@ -790,11 +853,11 @@
async fetchGeneExpression(gene){
console.log('fetchGeneExpression', gene);
const expressionDataPoint = this.renderConfig["data points"].find(x => x.role === "expression");
- const expressionUrl = this.updateDataUrl(expressionDataPoint.url, expressionDataPoint.parameters);
+ const expressionUrl = expressionDataPoint.url.replace('$datasetId', this.datasetId).replace('$gene', gene);
//this.isLoading = true;
await Vue.nextTick();
try{
- const response = await fetch(expressionUrl+','+gene);
+ const response = await fetch(expressionUrl);
const json = await response.json();
const expression = json.data[0]['expression'];
this.geneNames.push(gene);
@@ -926,6 +989,17 @@
return false;
},
+ handleSelectorUpdate(e, group, id){
+ console.log('selector updated', group, id, e);
+ this.cellCompositionVars[group].highlightLabels = e.coloredLabels;
+ this.selectColorBy(e.coloredField, group);
+ },
+
+ handleSelectorHover(e, group, id){
+ console.log('selector hovered', group, id, e);
+ this.cellCompositionVars[group].highlightLabel = e.hoveredLabel;
+ },
+
/*
cell composition
*/
diff --git a/src/components/researchPortal/ResearchSingleCellSelector.vue b/src/components/researchPortal/ResearchSingleCellSelector.vue
new file mode 100644
index 000000000..3a6872958
--- /dev/null
+++ b/src/components/researchPortal/ResearchSingleCellSelector.vue
@@ -0,0 +1,300 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/researchPortal/ResearchUmapPlot.vue b/src/components/researchPortal/ResearchUmapPlot.vue
index 9c2b91f72..6c298fbbc 100644
--- a/src/components/researchPortal/ResearchUmapPlot.vue
+++ b/src/components/researchPortal/ResearchUmapPlot.vue
@@ -3,12 +3,15 @@
{{ title }}
@@ -24,7 +27,7 @@
@mouseleave="endPan"
>
-
+
@@ -221,7 +224,7 @@
this.pointBoundsCalculated = true;
}
- if (!this.clusterCentersInitialized && this.fields) {
+ if (this.fields && !this.clusterCentersInitialized) {
this.clusterCenters = {};
points.forEach((coord, index) => {
@@ -560,15 +563,15 @@
.umapTooltip.hidden{
display:none;
}
- .tooltip{
+.scb-tooltip{
position:fixed;
background: white;
padding: 5px 10px;
box-shadow: rgba(0, 0, 0, 0.5) -4px 9px 25px -6px;
- }
- .tooltip.show{
+}
+.scb-tooltip.show{
opacity: 1;
- }
+}
button {
border: 1px solid rgba(0, 0, 0, .25);
diff --git a/src/utils/formatters.js b/src/utils/formatters.js
index 1849b465a..e3f3183ef 100644
--- a/src/utils/formatters.js
+++ b/src/utils/formatters.js
@@ -655,8 +655,8 @@ function BYORColumnFormatter(VALUE, KEY, CONFIG, PMAP, DATA_SCORES) {
${item.authors} ${item.publication}
${item.description}