|
257 | 257 | /> |
258 | 258 | </div> |
259 | 259 |
|
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 | | - |
277 | 260 | <div v-if="!cellCompositionVars.segmentByLabel || (displayFields && displayFields[cellCompositionVars.segmentByLabel].dataType==='cat')" style="display:flex; flex-direction: column; gap:5px"> |
278 | 261 | <research-stacked-bar-plot |
279 | 262 | :data="cellCompositionVars.segmentByCounts2" |
|
647 | 630 | </div> |
648 | 631 |
|
649 | 632 | </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> |
650 | 785 | </div> |
651 | 786 | </div> |
652 | 787 | </template> |
|
833 | 968 | viewType: 1, |
834 | 969 | |
835 | 970 | 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' }}, |
838 | 976 | ], |
839 | 977 | currentDatasetsPage: 1, |
840 | 978 | totalDatasets: null, |
|
1034 | 1172 | clean(){ |
1035 | 1173 | this.allMetadata = null; |
1036 | 1174 | 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 | +
|
1037 | 1187 | this.dataLoaded = false; |
1038 | 1188 | this.dataReady = false; |
1039 | 1189 | this.expressionData = {}; |
1040 | 1190 | this.geneNames = []; |
1041 | | - this.markersList = []; |
1042 | 1191 | this.expressionStatsAll = []; |
1043 | 1192 | this.genesNotFound = []; |
1044 | 1193 | this.dotPlotCellType = "", |
|
1150 | 1299 | } |
1151 | 1300 |
|
1152 | 1301 | //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 | + } |
1160 | 1311 | } |
1161 | 1312 |
|
1162 | 1313 | //fetch markers |
@@ -1963,6 +2114,10 @@ button:hover { |
1963 | 2114 | text-align: center; |
1964 | 2115 | } |
1965 | 2116 |
|
| 2117 | + ::v-deep .b-table-sticky-header { |
| 2118 | + padding: 0 10px; |
| 2119 | + } |
| 2120 | +
|
1966 | 2121 | ::v-deep .b-table-sticky-header th.position-relative { |
1967 | 2122 | position: sticky !important; |
1968 | 2123 | } |
|
0 commit comments