Skip to content

Commit 4632bff

Browse files
authored
-scb page updates, -scb on tissue page: show cell abundance, show mar… (#954)
-scb page updates, -scb on tissue page: show cell abundance, show markers
1 parent 1976fca commit 4632bff

File tree

3 files changed

+342
-124
lines changed

3 files changed

+342
-124
lines changed

src/components/researchPortal/singleCellBrowser/ResearchSingleCellBrowser.vue

Lines changed: 182 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -257,23 +257,6 @@
257257
/>
258258
</div>
259259

260-
261-
<!--
262-
<div style="display:flex; gap:20px; align-items: center; justify-content: space-between;">
263-
<div v-if="cellCompositionVars.segmentByLabel && displayFields && displayFields[cellCompositionVars.segmentByLabel].dataType==='cat'"
264-
style="display:flex; gap:10px; height: fit-content">
265-
<div class="plot-toggle" @click="isStacked = !isStacked">
266-
<div class="plot-toggle-btn" :class="`${isStacked?'':'toggled'}`">group</div>
267-
<div class="plot-toggle-btn" :class="`${isStacked?'toggled':''}`">stack</div>
268-
</div>
269-
<div class="plot-toggle" @click="isNormalized = !isNormalized">
270-
<div class="plot-toggle-btn" :class="`${isNormalized?'':'toggled'}`">count</div>
271-
<div class="plot-toggle-btn" :class="`${isNormalized?'toggled':''}`">pct.</div>
272-
</div>
273-
</div>
274-
</div>
275-
-->
276-
277260
<div v-if="!cellCompositionVars.segmentByLabel || (displayFields && displayFields[cellCompositionVars.segmentByLabel].dataType==='cat')" style="display:flex; flex-direction: column; gap:5px">
278261
<research-stacked-bar-plot
279262
:data="cellCompositionVars.segmentByCounts2"
@@ -647,6 +630,158 @@
647630
</div>
648631

649632
</div>
633+
<!-- layout 1 (umap-expression, violins-expression/cell type)-->
634+
<div v-if="layout===3" style="display:flex; flex-direction:column; width:100%; align-self:center;">
635+
<research-single-cell-info
636+
:data="metadata"
637+
/>
638+
<div v-if="dataReady" style="display:flex; gap:40px; flex:1">
639+
<div style="display: flex; flex-direction: column; gap:20px; flex: 1;">
640+
<!-- cell counts -->
641+
<div style="display: flex; flex-direction: column; flex:1; gap:20px; padding:20px; background: white;">
642+
<div style="display:flex; justify-content: space-between; gap:10px">
643+
<div style="font-size: 16px;">
644+
<span style="font-weight: bold">{{isATACseq ? 'Nuclei' : 'Cell'}} {{ isNormalized ? 'Proportion' : 'Count' }}</span>
645+
<template v-if="displayFields && cellCompositionVars.segmentByLabel && displayFields[cellCompositionVars.segmentByLabel].dataType==='cat'">
646+
by <span style="font-style: italic;">{{ displayLabel(cellCompositionVars.displayByLabel) }}</span>
647+
per <span style="font-style: italic;">{{ displayLabel(cellCompositionVars.segmentByLabel) }}</span>
648+
</template>
649+
<template v-else-if="cellCompositionVars.segmentByLabel">
650+
by <span style="font-style: italic;">{{ displayLabel(cellCompositionVars.segmentByLabel) }}</span>
651+
per <span style="font-style: italic;">{{ displayLabel(cellCompositionVars.displayByLabel) }}</span>
652+
</template>
653+
<template v-else>
654+
by <span style="font-style: italic;">{{ displayLabel(cellCompositionVars.displayByLabel) }}</span>
655+
</template>
656+
<template v-if="displayFields && cellCompositionVars.segmentByLabel && displayFields[cellCompositionVars.segmentByLabel].dataType==='cont'">
657+
<div style="font-size: 12px;">
658+
Each point represents the average {{isATACseq ? 'nuclei' : 'cell'}} {{ isNormalized ? 'proportion' : 'distribution' }} per {{ this.aggregateType }}
659+
</div>
660+
</template>
661+
</div>
662+
663+
<download-chart
664+
class="download"
665+
chartId="sc_stacked_bar_plot"
666+
style="width: 125px; align-self: flex-start;"
667+
:style="`${contCountResults?'pointer-events:none; opacity:0.5':''}`"
668+
/>
669+
</div>
670+
671+
<div v-if="!cellCompositionVars.segmentByLabel || (displayFields && displayFields[cellCompositionVars.segmentByLabel].dataType==='cat')" style="display:flex; flex-direction: column; gap:5px">
672+
<research-stacked-bar-plot
673+
:data="cellCompositionVars.segmentByCounts2"
674+
:primaryKey="cellCompositionVars.segmentByLabel ? cellCompositionVars.segmentByLabel : cellCompositionVars.displayByLabel"
675+
:subsetKey="cellCompositionVars.segmentByLabel ? cellCompositionVars.displayByLabel : cellCompositionVars.segmentByLabel"
676+
:xAxisLabel="cellCompositionVars.segmentByLabel ? displayLabel(cellCompositionVars.segmentByLabel) : displayLabel(cellCompositionVars.displayByLabel)"
677+
:yAxisLabel="`${isNormalized?('Percent of ' + (isATACseq ? 'Nuclei' :'Cells')):('Number of ' + (isATACseq ? 'Nuclei' : 'Cells'))}`"
678+
:highlightKey="cellCompositionVars.highlightLabel"
679+
:normalize="isNormalized"
680+
:stack="cellCompositionVars.segmentByLabel ? true : false"
681+
/>
682+
<div style="font-size:12px; opacity:0.5">{{ cellCompositionVars.segmentByLabel ? displayLabel(cellCompositionVars.displayByLabel) : displayLabel(cellCompositionVars.segmentByLabel) }}</div>
683+
<research-single-cell-selector
684+
:data="fields['metadata_labels']"
685+
layout="list"
686+
listDirection="horizontal"
687+
listAlignment="start"
688+
:colors="labelColors"
689+
:selectedField="cellCompositionVars.segmentByLabel ? cellCompositionVars.displayByLabel : cellCompositionVars.segmentByLabel"
690+
@on-update="handleSelectorUpdate($event)"
691+
@on-hover="handleSelectorHover($event)"
692+
/>
693+
</div>
694+
695+
<div v-if="contCountResults">
696+
<div style="font-size:12px; opacity:0.5">{{ displayLabel(cellCompositionVars.displayByLabel) }}</div>
697+
<div style="display:flex; flex-wrap: wrap; gap: 10px;">
698+
<div v-for="item in contCountResults" style="min-width: 250px; flex:1;">
699+
<div>{{ item.groupKey }}</div>
700+
<research-scatter-plot
701+
:data="item.data"
702+
:width="300"
703+
:height="150"
704+
:xKey="cellCompositionVars.segmentByLabel"
705+
yKey="cell_proportion"
706+
:xLabel="displayLabel(cellCompositionVars.segmentByLabel)"
707+
yLabel="Cell Proportion"
708+
:yDomain="[0, 1]"
709+
renderAs="svg"
710+
/>
711+
</div>
712+
</div>
713+
</div>
714+
</div>
715+
<!-- Marker genes -->
716+
<div style="display:flex; gap:25px">
717+
<div v-if="markers && (markerGenes || expressionStatsAll.length>0)" style="display:flex; flex-direction: column; gap:20px; background:white; padding:20px; width:100%">
718+
<div style="display:flex; flex-direction: column; gap:20px; min-width: 50%;">
719+
<div style="display:flex; justify-content: space-between;">
720+
<div style="display:flex; flex-direction: column;">
721+
<strong style="font-size: 16px;">{{ dotPlotCellType!=""?`Marker Genes for ${dotPlotCellType}` : 'Top Marker Genes by Cell Type' }}</strong>
722+
<div style="font-size:12px; opacity:0.5">Ranked by {{markersHaveZscores ? 'z-score' : 'mean expression'}}</div>
723+
</div>
724+
<div style="display:flex; gap:20px">
725+
<div style="display:flex; gap:5px" class="legends">
726+
<div style="display:flex; flex-direction: column;" class="legend">
727+
<div class="label">Mean Expression</div>
728+
<div class="gradient" :style="`background: linear-gradient(to right, ${colorScalePlasmaColorsArray});`"></div>
729+
<div style="display:flex" class="marks"><div>0.0</div><div>{{markerGenesMaxMean}}</div></div>
730+
</div>
731+
<div style="display:flex; flex-direction: column;" class="legend">
732+
<div class="label">% Cells Expressing</div>
733+
<div style="display:flex" class="circles">
734+
<div class="circleBorder"><div class="circle" style="height:20%"></div></div>
735+
<div class="circleBorder"><div class="circle" style="height:40%"></div></div>
736+
<div class="circleBorder"><div class="circle" style="height:60%"></div></div>
737+
<div class="circleBorder"><div class="circle" style="height:80%"></div></div>
738+
<div class="circleBorder"><div class="circle" style="height:100%"></div></div>
739+
</div>
740+
<div style="display:flex" class="marks"><div>0</div><div>100</div></div>
741+
</div>
742+
</div>
743+
<download-chart
744+
class="download"
745+
chartId="sc_dot_plot"
746+
style="width: 125px; align-self: flex-start;"
747+
/>
748+
</div>
749+
750+
</div>
751+
752+
<research-dot-plot
753+
style="display:flex; align-self: center"
754+
:data="markerGenes || expressionStatsAll"
755+
data-blah="pct_cells_expression"
756+
yKey="cell_type"
757+
xKey="gene"
758+
yLabel="Cell Type"
759+
xLabel="Gene"
760+
fillKey="mean_expression"
761+
:sizeKey="markerGenesSizeKey"
762+
:fitToSize="true"
763+
:cellWidth="30"
764+
highlightKey=""
765+
/>
766+
</div>
767+
<b-table v-if="markerGenesTable"
768+
style="font-size:12px;"
769+
:items="markerGenesTable"
770+
:fields="markerTableColumns"
771+
striped
772+
hover
773+
small
774+
responsive="sm"
775+
head-variant="light"
776+
sticky-header="300px"
777+
>
778+
</b-table>
779+
</div>
780+
</div>
781+
</div>
782+
</div>
783+
784+
</div>
650785
</div>
651786
</div>
652787
</template>
@@ -833,8 +968,11 @@
833968
viewType: 1,
834969
835970
tableColumns: [
836-
{key: "tissue", label: "Tissue", class:"capitalize"},
837-
{key: "totalCells", label: "Total Cells", formatter: (val) => val?.toLocaleString()}
971+
{key: "tissue", label: "Tissue", class:"capitalize"},
972+
{key: "depot", label: "Depot", class:"capitalize"},
973+
{key: "totalDonors", label: "Donors", formatter: (val) => val?.toLocaleString(), thClass: 'text-right', tdClass: 'text-right', thStyle: { width: '150px' }},
974+
{key: "totalBiosamples", label: "Biosamples", formatter: (val) => val?.toLocaleString(), thClass: 'text-right', tdClass: 'text-right', thStyle: { width: '150px' }},
975+
{key: "totalSamples", label: "Samples", formatter: (val) => val?.toLocaleString(), thClass: 'text-right', tdClass: 'text-right', thStyle: { width: '150px' }},
838976
],
839977
currentDatasetsPage: 1,
840978
totalDatasets: null,
@@ -1034,11 +1172,22 @@
10341172
clean(){
10351173
this.allMetadata = null;
10361174
this.metadata = null;
1175+
1176+
this.fields = null;
1177+
this.coordinates = null;
1178+
this.markers = null;
1179+
1180+
this.markersList = null;
1181+
this.markerCellTypes = null;
1182+
this.markerGenes = null;
1183+
this.markerGenesTable = null;
1184+
this.markersByGene = null;
1185+
this.markersByCellType = null;
1186+
10371187
this.dataLoaded = false;
10381188
this.dataReady = false;
10391189
this.expressionData = {};
10401190
this.geneNames = [];
1041-
this.markersList = [];
10421191
this.expressionStatsAll = [];
10431192
this.genesNotFound = [];
10441193
this.dotPlotCellType = "",
@@ -1150,13 +1299,15 @@
11501299
}
11511300
11521301
//fetch coordinates
1153-
this.preloadItem = 'coordinates';
1154-
const coordinatesEnpoint = this.selectedBI+this.BIendpoints.coordinates;
1155-
this.coordinates = await scUtils.fetchCoordinates(coordinatesEnpoint, this.datasetId);
1156-
if(this.coordinates){
1157-
llog('coordinates', this.coordinates);
1158-
}else{
1159-
llog('there was an error getting coordinates');
1302+
if(this.layout !== 3){
1303+
this.preloadItem = 'coordinates';
1304+
const coordinatesEnpoint = this.selectedBI+this.BIendpoints.coordinates;
1305+
this.coordinates = await scUtils.fetchCoordinates(coordinatesEnpoint, this.datasetId);
1306+
if(this.coordinates){
1307+
llog('coordinates', this.coordinates);
1308+
}else{
1309+
llog('there was an error getting coordinates');
1310+
}
11601311
}
11611312
11621313
//fetch markers
@@ -1963,6 +2114,10 @@ button:hover {
19632114
text-align: center;
19642115
}
19652116
2117+
::v-deep .b-table-sticky-header {
2118+
padding: 0 10px;
2119+
}
2120+
19662121
::v-deep .b-table-sticky-header th.position-relative {
19672122
position: sticky !important;
19682123
}

0 commit comments

Comments
 (0)