Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Created Cell EFP View #28

Merged
merged 12 commits into from
Nov 16, 2023
1 change: 0 additions & 1 deletion Eplant/UI/Layout/ViewContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export function ViewContainer<T, S, A>({
} & BoxProps) {
const { activeData, error, loading, loadingAmount, dispatch, state } =
useViewData(view, gene)

const idLabel = React.useId()
const selectId = React.useId()
const [printing, setPrinting] = usePrinting()
Expand Down
1 change: 0 additions & 1 deletion Eplant/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export const defaultConfig = {
}
// For some reason this is necessary to make the tabs work, maybe FlexLayout uses a Jotai provider?
const eplantScope = Symbol('Eplant scope')

function RootApp() {
const [darkMode, setDarkMode] = useDarkMode()
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import GeneticElement from "@eplant/GeneticElement";
import { ViewDataError } from "@eplant/View/viewData";
import EFP from ".";
import EFP, { getEFPSampleData } from "../eFP";
import _ from 'lodash'
import { EFPData, EFPGroup, EFPId, EFPTissue } from "./types";
import { EFPData, EFPGroup, EFPId, EFPTissue } from "../eFP/types";
import React from "react";
import CellSVGTooltip from "../eFP/Tooltips/cellEFPTooltip";

export default class CellEFP extends EFP{
constructor(
tooltipComponent: (props: { el: SVGElement | null; group: EFPGroup; tissue: EFPTissue; data: EFPData; }) => React.JSX.Element;
constructor(
public name: string,
public id: EFPId,
public svgURL: string,
public xmlURL: string
) {
super(name, id, svgURL, xmlURL);
this.tooltipComponent = CellSVGTooltip
alexwaeseperlman marked this conversation as resolved.
Show resolved Hide resolved
}

// Override
getInitialData = async (
gene: GeneticElement | null,
loadEvent: (val: number) => void
Expand Down Expand Up @@ -70,7 +73,7 @@ export default class CellEFP extends EFP{
const tissues: EFPTissue[] = group.tissues.map((tissue) => ({
name: tissue.name,
id: tissue.id,
...this._getEFPSampleData(
...getEFPSampleData(
tissue.samples
.map((name) => data[name.toLowerCase()]||0)
.filter((n) => Number.isFinite(n))
Expand All @@ -80,7 +83,7 @@ export default class CellEFP extends EFP{
return {
name: group.name,
tissues: tissues.filter((t) => t.samples > 0),
...this._getEFPSampleData(tissueValues),
...getEFPSampleData(tissueValues),
}
}).filter((g) => Number.isFinite(g.mean))

Expand Down
17 changes: 9 additions & 8 deletions Eplant/views/CellEFP/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import * as React from 'react'
export default styled((props) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path d="M20.2573 0.500008C18.0687 0.496985 15.941 1.37872 14.4035 2.99125C14.4034 2.99125 14.4034 2.99144 14.4034 2.99144C12.5067 4.98218 11.7899 7.80009 12.4965 10.4301C11.7218 11.733 11.1167 13.1451 10.767 14.7081C10.6077 14.3831 10.4356 14.0661 10.2527 13.756C10.8507 11.4709 10.2219 9.02883 8.57598 7.30109V7.30128C8.57598 7.30109 8.57579 7.30109 8.57579 7.30109C7.23324 5.89301 5.37531 5.12312 3.46446 5.12593C2.92944 5.12668 2.3904 5.18789 1.85726 5.31278L1.87294 5.31108V5.31089C1.74125 5.33866 1.61939 5.40101 1.51983 5.49151C1.42026 5.58201 1.34658 5.69744 1.30634 5.82592C0.571027 8.19455 1.18164 10.7752 2.89956 12.5778C2.89956 12.5778 2.89975 12.5778 2.89975 12.578C4.48277 14.2383 6.78243 15.0109 9.03982 14.6765C9.81668 16.0351 10.3368 17.5229 10.4706 19.2325V22.7645L10.4708 22.7643C10.4708 22.9654 10.5505 23.1581 10.6928 23.3003C10.8348 23.4424 11.0276 23.5223 11.2286 23.5223C11.4298 23.5223 11.6225 23.4424 11.7646 23.3003C11.9068 23.1581 11.9867 22.9654 11.9867 22.7643V16.7747C12.1458 14.7333 12.7744 12.9617 13.71 11.347C16.3223 11.7616 18.9925 10.8781 20.8251 8.9567L20.8249 8.95689V8.9567C22.7923 6.89263 23.4911 3.93872 22.6492 1.22732V1.22751C22.609 1.09904 22.5353 0.983598 22.4357 0.893101C22.3362 0.802603 22.2143 0.740254 22.0826 0.712294L22.0983 0.714183C21.4877 0.571164 20.8701 0.501073 20.2574 0.500125L20.2573 0.500008ZM20.2548 2.01599C20.6083 2.01637 20.9637 2.04547 21.3179 2.10366C21.8042 4.16942 21.2185 6.34681 19.7279 7.91097C18.4043 9.29903 16.5353 10.0211 14.6388 9.92213C15.7714 8.35589 17.1743 6.91869 18.6728 5.48981L18.6726 5.49C18.8181 5.35133 18.9026 5.16032 18.9073 4.95947C18.9122 4.75846 18.8368 4.56385 18.6982 4.41836C18.5436 4.25606 18.3252 4.17067 18.1015 4.18484C17.9237 4.19618 17.7556 4.26986 17.6265 4.39266C16.2473 5.70764 14.8984 7.07848 13.7478 8.58731C13.6991 6.92584 14.3112 5.28632 15.5009 4.03751C16.7465 2.73105 18.475 2.01388 20.2549 2.01615L20.2548 2.01599ZM3.46746 6.64177C4.96966 6.63969 6.428 7.24504 7.47885 8.34706C8.40931 9.32381 8.92074 10.5829 8.9574 11.8774C8.00575 10.669 6.91316 9.56318 5.80074 8.50256V8.50275C5.6717 8.37975 5.50355 8.30607 5.32577 8.29473C5.10208 8.28056 4.88367 8.36615 4.72912 8.52825C4.59045 8.67373 4.51507 8.86832 4.51998 9.06937C4.5247 9.27039 4.60916 9.46121 4.75463 9.5999C5.99005 10.7779 7.14609 11.9587 8.09286 13.2349C6.5612 13.2602 5.06771 12.6545 3.99741 11.5319C2.75673 10.2302 2.2604 8.42625 2.64128 6.70548C2.91674 6.66373 3.19294 6.64238 3.46766 6.642L3.46746 6.64177Z" />
</svg>
xmlns="http://www.w3.org/2000/svg"
width="28"
height="28"
viewBox="0 0 100 100"
{...props}
>
<path d="M39.4 20.5C20.9 24.5 7 38 7 52c0 14.1 14 27.6 32.8 31.6C68.5 89.6 98 73.6 98 52c0-14.1-14-27.6-32.8-31.6-8.2-1.7-17.7-1.7-25.8.1zm9.5 17.1c4.4.9 9.1 5.5 9.1 8.9 0 8.8-17.3 12.7-25 5.5-4-3.7-4-7.3 0-11 3.9-3.7 9.1-4.7 15.9-3.4z" />
</svg>
)
})(({ theme }) => ({
fill: theme.palette.text.primary,
}))

22 changes: 9 additions & 13 deletions Eplant/views/CellEFP/index.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
import { Forest } from '@mui/icons-material'
import React from 'react'
import EFP from '../eFP'
import EFPViewer from '../eFP/Viewer'
import PlantEFPIcon from './icon'
import CellEFPIcon from './icon'
import Thumbnail from '../../../thumbnails/plant_efp.png'
import { EFPViewerData } from '../eFP/Viewer/types'
import { efpFactory } from '../eFP/efpFactory'

import { makeCellEfps } from '../eFP/Viewer/util'

const views: EFPViewerData['views'] = [
{
name: 'cellEFP',
id: 'cellefp',
svgURL:
'https://bar.utoronto.ca/eplant/data/cell/Arabidopsis_thaliana.svg',
xmlURL:
'https://bar.utoronto.ca/eplant/data/cell/Arabidopsis_thaliana.xml',
}
name: 'cellEFP',
id: 'cellefp',
svgURL: 'https://bar.utoronto.ca/eplant/data/cell/Arabidopsis_thaliana.svg',
xmlURL: 'https://bar.utoronto.ca/eplant/data/cell/Arabidopsis_thaliana.xml',
},
]
const efps: EFP[] = efpFactory.makeCellEfps(views);
const efps: EFP[] = makeCellEfps(views)

export default new EFPViewer(
'cell',
'Cell eFP',
views,
efps,
() => <PlantEFPIcon />,
() => <CellEFPIcon />,
'Visualize gene expression over time on a developmental map.',
Thumbnail
)
4 changes: 2 additions & 2 deletions Eplant/views/ExperimentEFP/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import ExperimentEFPIcon from './icon'
import Thumbnail from '../../../thumbnails/tissue_efp.png'
import { EFPViewerData } from '../eFP/Viewer/types'
import EFP from '../eFP'
import { efpFactory } from '../eFP/efpFactory'
import { makeEfps } from '../eFP/Viewer/util'

const views: EFPViewerData['views'] = [
{
Expand Down Expand Up @@ -258,7 +258,7 @@ const views: EFPViewerData['views'] = [
},
]

const efps: EFP[] = efpFactory.makeEfps(views);
const efps: EFP[] = makeEfps(views)

export default new EFPViewer(
'tissue',
Expand Down
4 changes: 2 additions & 2 deletions Eplant/views/PlantEFP/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import EFP from '../eFP'
import EFPViewer from '../eFP/Viewer'
import PlantEFPIcon from './icon'
import Thumbnail from '../../../thumbnails/plant_efp.png'
import { efpFactory } from '../eFP/efpFactory'
import { makeEfps } from '../eFP/Viewer/util'
import { EFPViewerData } from '../eFP/Viewer/types'

const views: EFPViewerData['views'] = [
Expand All @@ -25,7 +25,7 @@ const views: EFPViewerData['views'] = [
'https://bar.utoronto.ca/eplant/data/plant/Klepikova/Arabidopsis_thaliana.xml',
},
]
const efps: EFP[] = efpFactory.makeEfps(views);
const efps: EFP[] = makeEfps(views)

export default new EFPViewer(
'plant',
Expand Down
106 changes: 106 additions & 0 deletions Eplant/views/eFP/Tooltips/EFPTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Box, Grow, Popper, Table, TableBody, TableCell, TableRow, useTheme } from "@mui/material"
import React from "react"
import { EFPGroup, EFPTissue, EFPData } from "../types"

function SVGTooltip(props: {
el: SVGElement | null
group: EFPGroup
tissue: EFPTissue
data: EFPData
}) {
const [open, setOpen] = React.useState(false)
const theme = useTheme()
React.useEffect(() => {
const enterListener = () => {
setOpen(true)
}
const leaveListener = () => {
setOpen(false)
}
if (props.el) {
props.el.addEventListener('mouseenter', enterListener)
props.el.addEventListener('mouseleave', leaveListener)
return () => {
if (props.el) {
props.el.removeEventListener('mouseenter', enterListener)
props.el.removeEventListener('mouseleave', leaveListener)
setOpen(false)
}
}
}
}, [props.el])
return (
<Popper transition anchorEl={props.el} open={open}>
{({ TransitionProps }) => (
<Grow {...TransitionProps} timeout={350}>
<Box
sx={(theme) => ({
backgroundColor: theme.palette.background.transparentOverlay,
backdropFilter: 'blur(7px)',
boxShadow: theme.shadows[3],
borderRadius: 1,
})}
>
<Table size="small">
<TableBody>
<TableRow>
<TableCell
sx={{
color: theme.palette.secondary.main,
textAlign: 'right',
}}
>
Sample name
</TableCell>
<TableCell>{props.tissue.name}</TableCell>
</TableRow>
<TableRow>
<TableCell
sx={{
color: theme.palette.secondary.main,
textAlign: 'right',
}}
>
Level
</TableCell>
<TableCell>
{props.tissue.mean.toFixed(2)}±{props.tissue.std.toFixed(2)}
</TableCell>
</TableRow>
<TableRow>
<TableCell
sx={{
color: theme.palette.secondary.main,
textAlign: 'right',
}}
>
Samples
</TableCell>
<TableCell>{props.tissue.samples}</TableCell>
</TableRow>
<TableRow>
<TableCell
sx={{
color: theme.palette.secondary.main,
textAlign: 'right',
borderBottom: 'none',
}}
>
Log2 fold change vs control
</TableCell>
<TableCell sx={{ borderBottom: 'none' }}>
{Math.log2(
props.tissue.mean / (props.data.control ?? 1)
).toFixed(2)}
</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Grow>
)}
</Popper>
)
}

export default SVGTooltip;
74 changes: 74 additions & 0 deletions Eplant/views/eFP/Tooltips/cellEFPTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Popper, Grow, Box, Table, TableBody, TableRow, TableCell, useTheme } from "@mui/material"
import { EFPGroup, EFPTissue, EFPData } from "../types"
import React from "react"

function CellSVGTooltip(props: {
el: SVGElement | null
group: EFPGroup
tissue: EFPTissue
data: EFPData
}) {
const [open, setOpen] = React.useState(false)
const theme = useTheme()
React.useEffect(() => {
const enterListener = () => {
setOpen(true)
}
const leaveListener = () => {
setOpen(false)
}
if (props.el) {
props.el.addEventListener('mouseenter', enterListener)
props.el.addEventListener('mouseleave', leaveListener)
return () => {
if (props.el) {
props.el.removeEventListener('mouseenter', enterListener)
props.el.removeEventListener('mouseleave', leaveListener)
setOpen(false)
}
}
}
}, [props.el])
return (
<Popper transition anchorEl={props.el} open={open}>
{({ TransitionProps }) => (
<Grow {...TransitionProps} timeout={350}>
<Box
sx={(theme) => ({
backgroundColor: theme.palette.background.transparentOverlay,
backdropFilter: 'blur(7px)',
boxShadow: theme.shadows[3],
borderRadius: 1,
})}
>
<Table size="small">
<TableBody>
<TableRow>
<TableCell>
{props.tissue.name.charAt(0).toUpperCase() + props.tissue.name.slice(1)}
</TableCell>
<TableCell></TableCell>
</TableRow>
<TableRow>
<TableCell
sx={{
color: theme.palette.secondary.main,
textAlign: 'left',
}}
>
Localization Score
</TableCell>
<TableCell>
{props.tissue.mean}
</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Grow>
)}
</Popper>
)
}

export default CellSVGTooltip;
Loading