diff --git a/Eplant/Eplant.tsx b/Eplant/Eplant.tsx index 06e629f5..1d9de465 100644 --- a/Eplant/Eplant.tsx +++ b/Eplant/Eplant.tsx @@ -42,7 +42,6 @@ import { Theme } from '@mui/system' import ErrorBoundary from './util/ErrorBoundary' import { dark, light } from './theme' - // TODO: Make this drawer support opening/closing on mobile const sideBarWidth = 300 diff --git a/Eplant/main.tsx b/Eplant/main.tsx index ab132ac7..19ea1b45 100644 --- a/Eplant/main.tsx +++ b/Eplant/main.tsx @@ -50,11 +50,11 @@ function RootApp() { return ( - - - - - + + + + + ) diff --git a/Eplant/views/eFP/EFPPreview.tsx b/Eplant/views/eFP/EFPPreview.tsx index 0ec2146c..8639ef39 100644 --- a/Eplant/views/eFP/EFPPreview.tsx +++ b/Eplant/views/eFP/EFPPreview.tsx @@ -56,10 +56,10 @@ export default function EFPPreview({ state={{ renderAsThumbnail: true, colorMode: colorModeDeferred, - maskThreshold: maskThreshold + maskThreshold: maskThreshold, }} geneticElement={gene} - dispatch={() => { }} + dispatch={() => {}} />
void - onSubmit: (threshhold: number) => void + state: EFPViewerState + onClose: () => void + onSubmit: (threshhold: number) => void } const MaskModal = ({ state, onClose, onSubmit }: MaskModalProps) => { - const [sliderValue, setSliderValue] = useState(state.maskThreshold); - const theme = useTheme() - const handleSliderChange = (event: Event, newValue: number | number[]) => { - setSliderValue(newValue as number); - }; + const [sliderValue, setSliderValue] = useState(state.maskThreshold) + const theme = useTheme() + const handleSliderChange = (event: Event, newValue: number | number[]) => { + setSliderValue(newValue as number) + } - const handleClose = () => { - setSliderValue(state.maskThreshold) - onClose(); - }; + const handleClose = () => { + setSliderValue(state.maskThreshold) + onClose() + } - const handleSubmit = () => { - onSubmit(sliderValue); - onClose(); - }; + const handleSubmit = () => { + onSubmit(sliderValue) + onClose() + } - return ( - -
- - Mask samples if the expression level is within a given range of their standard deviation. - - `${value}%`} - min={0} - max={100} - /> -
- - -
-
-
- ); -}; + return ( + +
+ + Mask samples if the expression level is within a given range of their + standard deviation. + + `${value}%`} + min={0} + max={100} + /> +
+ + +
+
+
+ ) +} -export default MaskModal; +export default MaskModal diff --git a/Eplant/views/eFP/Viewer/index.tsx b/Eplant/views/eFP/Viewer/index.tsx index 4a81982f..4de4bbc1 100644 --- a/Eplant/views/eFP/Viewer/index.tsx +++ b/Eplant/views/eFP/Viewer/index.tsx @@ -131,7 +131,7 @@ export default class EFPViewer public icon: () => JSX.Element, public description?: string, public thumbnail?: string, - ) { } + ) {} getInitialData = async ( gene: GeneticElement | null, loadEvent: (progress: number) => void, @@ -162,7 +162,6 @@ export default class EFPViewer viewData: viewData, efps: this.efps, colorMode: 'absolute' as const, - } } reducer = (state: EFPViewerState, action: EFPViewerAction) => { @@ -201,12 +200,12 @@ export default class EFPViewer case 'toggle-mask-modal': return { ...state, - maskModalVisible: state.maskModalVisible ? false : true + maskModalVisible: state.maskModalVisible ? false : true, } case 'set-mask-threshold': return { ...state, - maskThreshold: action.threshold + maskThreshold: action.threshold, } default: return state @@ -254,10 +253,10 @@ export default class EFPViewer state={{ colorMode: props.state.colorMode, renderAsThumbnail: false, - maskThreshold: props.state.maskThreshold + maskThreshold: props.state.maskThreshold, }} geneticElement={props.geneticElement} - dispatch={() => { }} + dispatch={() => {}} /> ) }, [ @@ -266,7 +265,7 @@ export default class EFPViewer props.dispatch, sortedViewData[activeViewIndex], props.state.colorMode, - props.state.maskThreshold + props.state.maskThreshold, ]) const ref = React.useRef(null) const dimensions = useDimensions(ref) @@ -387,7 +386,12 @@ export default class EFPViewer props.dispatch({ type: 'toggle-mask-modal' })} - onSubmit={(threshold) => props.dispatch({ type: 'set-mask-threshold', threshold: threshold })} + onSubmit={(threshold) => + props.dispatch({ + type: 'set-mask-threshold', + threshold: threshold, + }) + } /> ({ @@ -402,7 +406,7 @@ export default class EFPViewer state={{ colorMode: props.state.colorMode, renderAsThumbnail: false, - maskThreshold: props.state.maskThreshold + maskThreshold: props.state.maskThreshold, }} /> <>Mask data - } + render: () => <>Mask data, + }, ] header: View['header'] = ( props, diff --git a/Eplant/views/eFP/index.tsx b/Eplant/views/eFP/index.tsx index c7cc76c5..acb34f6c 100644 --- a/Eplant/views/eFP/index.tsx +++ b/Eplant/views/eFP/index.tsx @@ -20,7 +20,7 @@ export default class EFP implements View { getInitialState: () => EFPState = () => ({ colorMode: 'absolute', renderAsThumbnail: false, - maskThreshold: 100 + maskThreshold: 100, }) tooltipComponent: (props: { el: SVGElement | null @@ -52,8 +52,9 @@ export default class EFP implements View { const database = xml.getElementsByTagName('view')[0]?.getAttribute('db') let webservice = xml.getElementsByTagName('webservice')[0]?.textContent if (!webservice) - webservice = `https://bar.utoronto.ca/eplant/cgi-bin/plantefp.cgi?datasource=${database ?? 'atgenexp_plus' - }&` + webservice = `https://bar.utoronto.ca/eplant/cgi-bin/plantefp.cgi?datasource=${ + database ?? 'atgenexp_plus' + }&` // Get a list of groups and samples const sampleNames: string[] = [] @@ -95,9 +96,9 @@ export default class EFP implements View { chunks.map((names) => fetch( webservice + - `id=${gene.id}&samples=${encodeURIComponent( - JSON.stringify(names), - )}`, + `id=${gene.id}&samples=${encodeURIComponent( + JSON.stringify(names), + )}`, ) .then((res) => res.json()) .then( @@ -184,7 +185,12 @@ export default class EFP implements View { (props.geneticElement?.id ?? 'no-gene') + '-' + useMemo(() => Math.random().toString(16).slice(3), []) - const styles = useStyles(id, props.activeData, props.state.colorMode, props.state.maskThreshold) + const styles = useStyles( + id, + props.activeData, + props.state.colorMode, + props.state.maskThreshold, + ) useEffect(() => { const el = document.createElement('style') el.innerHTML = styles diff --git a/Eplant/views/eFP/svg.tsx b/Eplant/views/eFP/svg.tsx index 437c8c6f..aefb8d76 100644 --- a/Eplant/views/eFP/svg.tsx +++ b/Eplant/views/eFP/svg.tsx @@ -41,9 +41,9 @@ export const useEFPSVG = ( if (!cache[view.id]) return { view: null, loading: true } const parser = new DOMParser() const svg = parser.parseFromString(cache[view.id].svg, 'text/xml') - ;['width', 'height', 'x', 'y', 'id'].map((s) => - svg.documentElement.removeAttribute(s), - ) + ;['width', 'height', 'x', 'y', 'id'].map((s) => + svg.documentElement.removeAttribute(s), + ) svg.documentElement.setAttribute('class', 'eFP-svg') // Remove styling from all of the text tags for (const text of svg.querySelectorAll('text, tspan')) { @@ -85,19 +85,20 @@ export function getColor( theme: Theme, colorMode: ColorMode, tissueStd?: number, - maskThreshold?: number + maskThreshold?: number, ): string { const extremum = Math.max( Math.abs(Math.log2(group.min / control)), Math.log2(group.max / control), 1, ) - const masked = maskThreshold && tissueStd ? - isNaN(group.std) || (tissueStd >= value * (maskThreshold / 100)) : - false + const masked = + maskThreshold && tissueStd + ? isNaN(group.std) || tissueStd >= value * (maskThreshold / 100) + : false const norm = Math.log2(value / control) / extremum if (masked) { - return (theme.palette.secondary.dark) + return theme.palette.secondary.dark } else if (colorMode === 'relative') return norm < 0 ? mix(theme.palette.neutral.main, theme.palette.cold.main, Math.abs(norm)) @@ -121,7 +122,8 @@ export function useStyles( .flatMap((group) => group.tissues.map( (tissue) => ` - #${id} .efp-group-${tissue.id} *, #${id} .efp-group-${tissue.id + #${id} .efp-group-${tissue.id} *, #${id} .efp-group-${ + tissue.id } { fill: ${getColor( tissue.mean, group, @@ -130,7 +132,7 @@ export function useStyles( colorMode, tissue.std, maskThreshold, - )} !important; }` + )} !important; }`, ), ) .join('\n')