Skip to content
Snippets Groups Projects
Commit f95b95d4 authored by David Mendez's avatar David Mendez
Browse files

Cell health and viability: Use data from ex proxy endpoint

parent 07b2e823
No related branches found
No related tags found
1 merge request!80Add multiplex data visualisation
Showing
with 382 additions and 83 deletions
<template>
<div>
<template v-for="cellData in cellViabilityData">
<div :key="`${cellData.cellLine.name}-title`">
<template v-for="(cellData, cellLineID) in dataPerCell">
<div :key="`${cellLineID}-title`">
<v-banner single-line color="blue-grey lighten-4">
<div class="primary--text font-weight-bold">
{{ cellData.cellLine.name }}
{{ cellData.name }}
</div>
<template #actions>
<CellLineInfo />
<CellLineInfo :cell-line-i-d="cellLineID" />
</template>
</v-banner>
</div>
<CellPropsRows :key="cellData.cellLine.name" :cell-health="cellHealth" />
<v-divider :key="`${cellData.cellLine.name}-divider`" />
<CellPropsRows
:key="`${cellLineID}-props`"
:cell-health="cellHealth"
:time-points="timePoints"
:cell-line-data="dataPerCell[cellLineID]"
/>
<v-divider :key="`${cellData.name}-divider`" />
</template>
</div>
</template>
......@@ -30,6 +35,14 @@ export default {
type: Boolean,
default: () => false,
},
dataPerCell: {
type: Object,
default: () => {},
},
timePoints: {
type: Array,
default: () => [],
},
},
data() {
return {
......
<template>
<div class="d-flex justify-space-between">
<SingleCellCountDialog title="12h" />
<SingleCellCountDialog title="24h" />
<SingleCellCountDialog title="48h" />
<SingleCellCountDialog
:title="timePoints[0]"
:control-d-m-s-o-total-cell-count="controlDMSOCellCount"
:total-cell-count="cellCounts[0]"
/>
<SingleCellCountDialog
:title="timePoints[1]"
:control-d-m-s-o-total-cell-count="controlDMSOCellCount"
:total-cell-count="cellCounts[1]"
/>
<SingleCellCountDialog
:title="timePoints[2]"
:control-d-m-s-o-total-cell-count="controlDMSOCellCount"
:total-cell-count="cellCounts[2]"
/>
</div>
</template>
......@@ -12,6 +24,20 @@ export default {
components: {
SingleCellCountDialog,
},
props: {
timePoints: {
type: Array,
default: () => [],
},
cellCounts: {
type: Array,
default: () => [],
},
controlDMSOCellCount: {
type: Number,
default: () => 1,
},
},
}
</script>
......
......@@ -103,17 +103,21 @@ export default {
type: String,
default: () => '',
},
controlDMSOTotalCellCount: {
type: Number,
default: () => 1,
},
totalCellCount: {
type: Number,
default: () => 1,
},
},
data() {
return {
dialog: false,
controlDMSOTotalCellCount: 500,
}
},
computed: {
totalCellCount() {
return Math.floor(Math.random() * 500)
},
normalisedCount() {
return parseInt(
(this.totalCellCount / this.controlDMSOTotalCellCount) * 100
......
......@@ -2,28 +2,94 @@
<div class="text-center">
<v-dialog v-model="dialog" width="500">
<template #activator="{ on, attrs }">
<div>
<div>
{{ title }}
</div>
<v-btn color="primary" icon v-bind="attrs" v-on="on">
<v-icon> mdi-information-outline </v-icon>
</v-btn>
</div>
<v-btn color="primary" icon v-bind="attrs" v-on="on" @click="loadData">
<v-icon> mdi-information-outline </v-icon>
</v-btn>
</template>
<v-card>
<v-card v-if="!dataLoaded">
<v-skeleton-loader type="card"></v-skeleton-loader>
</v-card>
<v-card v-else>
<v-card-title class="text-h5 grey lighten-2">
Cell Line Info
{{ title }}
</v-card-title>
<v-divider />
<v-card-text>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
<v-simple-table>
<template #default>
<tbody>
<tr>
<td><b>Name:</b></td>
<td>{{ cellLineData.cell_name }}</td>
</tr>
<tr>
<td><b>Description:</b></td>
<td>{{ cellLineData.cell_description }}</td>
</tr>
<tr>
<td><b>Organism:</b></td>
<td>{{ cellLineData.cell_source_organism }}</td>
</tr>
<tr>
<td><b>Source Tissue:</b></td>
<td>{{ cellLineData.cell_source_tissue }}</td>
</tr>
</tbody>
</template>
</v-simple-table>
</v-card-text>
<v-card-subtitle> References </v-card-subtitle>
<v-card-text>
<v-simple-table>
<template #default>
<tbody>
<tr>
<td><b>ChEMBL:</b></td>
<td>
<a :href="linkToChEMBLReportCard">{{ cellLineID }}</a>
</td>
</tr>
<tr>
<td><b>Cell Line Ontology:</b></td>
<td>
<a v-if="thereIsCLOLink" :href="CLOLink">
{{ cellLineData.clo_id }}
</a>
<div v-else>---</div>
</td>
</tr>
<tr>
<td><b>Experimental Factor Ontology:</b></td>
<td>
<a v-if="thereIsEFOLink" :href="EFOLink">
{{ cellLineData.efo_id }}
</a>
<div v-else>---</div>
</td>
</tr>
<tr>
<td><b>Cellosaurus:</b></td>
<td>
<a v-if="thereIsCellosaurusLink" :href="CellosaurusLink">
{{ cellLineData.cellosaurus_id }}
</a>
<div v-else>---</div>
</td>
</tr>
<tr>
<td><b>LINCS Project:</b></td>
<td>
<a v-if="thereIsLINCSProjectLink" :href="LINCSProjectLink">
{{ cellLineData.cl_lincs_id }}
</a>
<div v-else>---</div>
</td>
</tr>
</tbody>
</template>
</v-simple-table>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
......@@ -36,9 +102,16 @@
</template>
<script>
import RequestNotifications from '~/web-components-submodule/utils/RequestNotifications.js'
import ESProxyService from '~/web-components-submodule/services/ESProxyService.js'
import EntityNames from '~/web-components-submodule/standardisation/EntityNames.js'
import IndexNames from '~/web-components-submodule/standardisation/IndexNames.js'
import ErrorTracking from '~/web-components-submodule/tracking/ErrorTracking.js'
import LinksToEntities from '~/web-components-submodule/standardisation/LinksToEntities.js'
export default {
props: {
title: {
cellLineID: {
type: String,
default: () => '',
},
......@@ -46,8 +119,80 @@ export default {
data() {
return {
dialog: false,
dataLoaded: false,
cellLineData: {},
}
},
computed: {
title() {
return this.cellLineData.cell_name == null
? this.cellLineID
: this.cellLineData.cell_name
},
thereIsCLOLink() {
return this.cellLineData.clo_id != null
},
thereIsEFOLink() {
return this.cellLineData.efo_id != null
},
thereIsCellosaurusLink() {
return this.cellLineData.cellosaurus_id != null
},
thereIsLINCSProjectLink() {
return this.cellLineData.cl_lincs_id != null
},
linkToChEMBLReportCard() {
return LinksToEntities[EntityNames.CellLine.entityID].getLinkToReportCard(
this.cellLineID
)
},
CLOLink() {
return `https://purl.obolibrary.org/obo/${this.cellLineData.clo_id}`
},
EFOLink() {
return `https://www.ebi.ac.uk/efo/${this.cellLineData.efo_id}`
},
CellosaurusLink() {
return `https://web.expasy.org/cellosaurus/${this.cellLineData.cellosaurus_id}`
},
LINCSProjectLink() {
return `https://life.ccs.miami.edu/life/summary?mode=CellLine&source=LINCS&input=${this.cellLineData.cellosaurus_id}`
},
},
methods: {
loadData() {
if (this.dataLoaded) {
return
}
const entityID = EntityNames.CellLine.entityID
const indexName = IndexNames.getIndexNameFromEntityID(entityID)
const source = [
'cell_name',
'cell_description',
'cell_source_organism',
'cell_source_tissue',
'cellosaurus_id',
'cl_lincs_id',
'clo_id',
'efo_id',
]
ESProxyService.getESDocument(indexName, this.cellLineID, source)
.then((response) => {
this.cellLineData = response.data._source
this.dataLoaded = true
})
.catch((error) => {
ErrorTracking.trackError(error, this)
RequestNotifications.dispatchRequestErrorNotification(
error,
this.$store.dispatch,
`There was an error while loading the data of cell line ${this.cellLineID}`
)
})
},
},
}
</script>
......
......@@ -3,13 +3,20 @@
<v-expansion-panel>
<v-expansion-panel-header> Images </v-expansion-panel-header>
<v-expansion-panel-content>
<ImagesInTime />
<ImagesInTime
:time-points="timePoints"
:image-u-r-l-s="cellLineData.imageURLS"
/>
</v-expansion-panel-content>
</v-expansion-panel>
<v-expansion-panel>
<v-expansion-panel-header> Properties </v-expansion-panel-header>
<v-expansion-panel-content>
<LineChart :cell-health="cellHealth" />
<LineChart
:cell-health="cellHealth"
:time-points="timePoints"
:cell-properties="cellLineData.properties"
/>
</v-expansion-panel-content>
</v-expansion-panel>
<v-expansion-panel>
......@@ -17,7 +24,11 @@
Normalised Cell Count
</v-expansion-panel-header>
<v-expansion-panel-content>
<CellCount />
<CellCount
:time-points="timePoints"
:cell-counts="cellLineData.cellCounts"
:control-d-m-s-o-cell-count="cellLineData.controlDMSOCellCount"
/>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
......@@ -39,6 +50,14 @@ export default {
type: Boolean,
default: () => false,
},
timePoints: {
type: Array,
default: () => [],
},
cellLineData: {
type: Object,
default: () => {},
},
},
computed: {
panels() {
......
......@@ -69,12 +69,14 @@ export default {
type: String,
default: () => '',
},
imgUrl: {
type: String,
default: () => '',
},
},
data() {
return {
dialog: false,
imgUrl:
'https://www.ebi.ac.uk/biostudies/files/S-BIAD145/processed_images/CQ1-ctf001_HEK_blanc/20211006T142945/B-02_F0001_T0001_Z0001.png',
}
},
}
......
<template>
<div>
<div class="d-flex justify-space-between">
<ImagesDialog title="12h" />
<ImagesDialog title="24h" />
<ImagesDialog title="48h" />
<ImagesDialog :title="timePoints[0]" :img-url="imageURLS[0]" />
<ImagesDialog :title="timePoints[1]" :img-url="imageURLS[1]" />
<ImagesDialog :title="timePoints[2]" :img-url="imageURLS[2]" />
</div>
</div>
</template>
......@@ -14,6 +14,16 @@ export default {
components: {
ImagesDialog,
},
props: {
timePoints: {
type: Array,
default: () => [],
},
imageURLS: {
type: Array,
default: () => [],
},
},
}
</script>
......
......@@ -23,23 +23,17 @@ export default {
type: Boolean,
default: () => false,
},
timePoints: {
type: Array,
default: () => [],
},
cellProperties: {
type: Object,
default: () => {},
},
},
data() {
return {
series: [
{
name: this.getMockName1(),
data: this.getRandomValues(),
},
{
name: this.getMockName2(),
data: this.getRandomValues(),
},
{
name: this.getMockName3(),
data: this.getRandomValues(),
},
],
chartOptions: {
chart: {
height: 350,
......@@ -55,7 +49,7 @@ export default {
width: [5, 5, 4],
curve: 'straight',
},
labels: ['12h', '24h', '48h'],
labels: this.timePoints,
xaxis: {},
yaxis: {
min: 0,
......@@ -71,22 +65,19 @@ export default {
},
}
},
methods: {
getRandomValues() {
const numbers = []
while (numbers.length < 3) {
numbers.push(parseInt(Math.random() * 100))
computed: {
series() {
const series = []
for (const propID in this.cellProperties) {
const propData = this.cellProperties[propID]
const propertyLabel = propData.label
const propertyValues = propData.values
series.push({
name: propertyLabel,
data: propertyValues,
})
}
return numbers
},
getMockName1() {
return this.cellHealth ? 'Mitochondrial mass' : 'Healthy nuclei'
},
getMockName2() {
return this.cellHealth ? 'Tubulin effect' : 'Fragmented nuclei'
},
getMockName3() {
return this.cellHealth ? 'Membrane permeabilized' : 'Pyknosed nuclei'
return series
},
},
}
......
......@@ -3,13 +3,13 @@
<v-dialog v-model="dialog" width="500">
<template #activator="{ on, attrs }">
<v-btn color="primary" outlined x-small v-bind="attrs" v-on="on">
Sample Images
Training Images
</v-btn>
</template>
<v-card>
<v-card-title class="text-h5 grey lighten-2">
Sample Images
Training Images
</v-card-title>
<v-container>
<v-row>
......
......@@ -6,12 +6,20 @@
<v-tabs>
<v-tab>Viability Properties</v-tab>
<v-tab>Cell Health Properties</v-tab>
<v-tab-item>
<div class="tab-item-content"><CellPropertiesPlots /></div
<div class="tab-item-content">
<CellPropertiesPlots
:data-per-cell="data.cellHealthProperties.dataPerCell"
:time-points="timePoints"
/></div
></v-tab-item>
<v-tab-item>
<div><CellPropertiesPlots cell-health /></div
<div class="tab-item-content">
<CellPropertiesPlots
:data-per-cell="data.viabilityProperties.dataPerCell"
cell-health
:time-points="timePoints"
/></div
></v-tab-item>
</v-tabs>
</v-card-text>
......@@ -30,6 +38,18 @@ export default {
type: String,
default: () => '',
},
data: {
type: Object,
default: () => {},
},
dataPerCell: {
type: Object,
default: () => {},
},
timePoints: {
type: Array,
default: () => [],
},
},
}
</script>
......
<template>
<v-card>
<v-card-text>
<div class="d-flex justify-center align-center">
<DataExplanationDialog />
</div>
</v-card-text>
<v-card-text>
<v-card-text v-if="!dataLoaded">
<v-row dense>
<v-col cols="12" sm="6">
<v-skeleton-loader type="card"></v-skeleton-loader>
</v-col>
<v-col cols="12" sm="6">
<v-skeleton-loader type="card"></v-skeleton-loader>
</v-col>
</v-row>
<v-row dense>
<v-col cols="12" sm="6">
<PlotsForConcentration concentration="1 µM" />
<v-skeleton-loader type="card"></v-skeleton-loader>
</v-col>
<v-col cols="12" sm="6">
<PlotsForConcentration concentration="10 µM" />
<v-skeleton-loader type="card"></v-skeleton-loader>
</v-col>
</v-row>
</v-card-text>
<template v-else>
<v-card-text>
<div class="d-flex justify-center align-center">
<DataExplanationDialog />
</div>
</v-card-text>
<v-card-text>
<v-row dense>
<v-col
v-for="(data, concentration) in dataPerConcentration"
:key="concentration"
cols="12"
sm="6"
>
<PlotsForConcentration
:concentration="concentration"
:data="data"
:time-points="timePoints"
/>
</v-col>
</v-row>
</v-card-text>
</template>
</v-card>
</template>
<script>
import RequestNotifications from '@/web-components-submodule/utils/RequestNotifications.js'
import PlotsForConcentration from '~/components/report_cards/chemical_probe/CellViabilityAndHealthComponents/PlotsForConcentration.vue'
import DataExplanationDialog from '~/components/report_cards/chemical_probe/CellViabilityAndHealthComponents/DataExplanation/DataExplanationDialog.vue'
import ESProxyService from '~/web-components-submodule/services/ESProxyService.js'
import ErrorTracking from '~/web-components-submodule/tracking/ErrorTracking.js'
export default {
components: {
PlotsForConcentration,
DataExplanationDialog,
},
props: {
itemID: {
type: String,
default: () => undefined,
},
},
data() {
return {
dataLoaded: false,
dataPerConcentration: {},
timePoints: [],
}
},
mounted() {
this.loadData()
},
methods: {
loadData() {
const visualisationPath = `/eubopen/visualisations/compound/cell_viability_and_health_data/${this.itemID}`
ESProxyService.getGenericData(visualisationPath)
.then((response) => {
this.timePoints = response.data.timePoints
this.dataPerConcentration = response.data.concentrations
this.dataLoaded = true
})
.catch((error) => {
ErrorTracking.trackError(error, this)
RequestNotifications.dispatchRequestErrorNotification(
error,
this.$store.dispatch,
`Target Classifications: There was an error while loading the Cell Viability and Health Data!`
)
})
},
},
}
</script>
......
......@@ -47,6 +47,8 @@ export default {
process.env.COMPOUND_REPORT_CARDS_BASE_URL || '/compound',
targetReportCardsBaseUrl:
process.env.TARGET_REPORT_CARDS_BASE_URL || '/target',
cellLineReportCardsBaseUrl:
process.env.CELL_LINE_REPORT_CARDS_BASE_URL || '/cell_line_report_card',
eubopenCompoundReportCardsBaseUrl:
process.env.EUBOPEN_COMPOUND_REPORT_CARDS_BASE_URL || '/compound',
eubopenTargetReportCardsBaseUrl:
......
Subproject commit 67aa79551387d49155c461d6d960a22bf685cb0a
Subproject commit f81fef0169491c7e605c3211ad9ccb87ee079f9c
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment