From 9dc8a0ae00b6fd963fbf9063c700c77012744700 Mon Sep 17 00:00:00 2001 From: Lukasz Kreft Date: Fri, 23 Feb 2018 15:22:33 +0100 Subject: [PATCH] added coordinates ID selection --- scope-client/src/components/App.jsx | 2 +- scope-client/src/components/AppSidebar.jsx | 46 +++++++++++++++++-- scope-client/src/components/common/API.jsx | 16 +++++-- scope-client/src/components/common/Viewer.jsx | 12 +++-- .../src/components/pages/Expression.jsx | 10 ++-- scope-client/src/components/pages/Regulon.jsx | 14 +++--- 6 files changed, 75 insertions(+), 25 deletions(-) diff --git a/scope-client/src/components/App.jsx b/scope-client/src/components/App.jsx index 8db8b2ce..348d3e71 100644 --- a/scope-client/src/components/App.jsx +++ b/scope-client/src/components/App.jsx @@ -18,7 +18,7 @@ export default class App extends Component { - + diff --git a/scope-client/src/components/AppSidebar.jsx b/scope-client/src/components/AppSidebar.jsx index abd3ddaf..af51dbd9 100644 --- a/scope-client/src/components/AppSidebar.jsx +++ b/scope-client/src/components/AppSidebar.jsx @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { Sidebar, Menu, Icon, Button, Divider, Modal, Checkbox, Grid, Input, Progress } from 'semantic-ui-react'; +import { Sidebar, Menu, Icon, Button, Divider, Modal, Checkbox, Dropdown, Grid, Input, Progress } from 'semantic-ui-react'; import FileReaderInput from 'react-file-reader-input'; import { BackendAPI } from './common/API'; @@ -8,9 +8,13 @@ export default class AppSidebar extends Component { super(); this.state = { activeLoom: null, + activeCoordinates: {}, uploadLoomFile: null, uploadLoomModalOpened: false, uploadLoomProgress: 0, + metadata: { + fileMetaData: {} + }, myLooms: [], settings: BackendAPI.getSettings() } @@ -18,6 +22,7 @@ export default class AppSidebar extends Component { } render () { + const { activeCoordinates } = this.state; return ( @@ -31,7 +36,16 @@ export default class AppSidebar extends Component { SETTINGS - + + + + + {this.myLoomCoordinates()} + + + + + @@ -78,7 +92,7 @@ export default class AppSidebar extends Component { let query = {}; BackendAPI.getConnection().then((gbc) => { gbc.services.scope.Main.getMyLooms(query, (error, response) => { - if (response !== null) { + if (response !== null) { console.log("Loaded .loom files: ", response.myLooms); this.setState({ myLooms: response.myLooms }); BackendAPI.setLoomFiles(response.myLooms); @@ -106,6 +120,17 @@ export default class AppSidebar extends Component { } } + myLoomCoordinates() { + const { activeCoordinates } = this.state; + if (this.state.metadata.cellMetaData) { + return this.state.metadata.cellMetaData.embeddings.map((coords) => { + return ( + + ); + }); + } + } + toggleUploadLoomModal(event) { this.setState({ uploadLoomModalOpened: !this.state.uploadLoomModalOpened }) } @@ -156,8 +181,19 @@ export default class AppSidebar extends Component { } setActiveLoom(l) { - this.setState({ activeLoom: l}) + BackendAPI.setActiveCoordinates(-1); BackendAPI.setActiveLoom(l); - console.log(l +" is now active!") + let metadata = BackendAPI.getActiveLoomMetadata(); + this.setState({ activeLoom: l, metadata: metadata}) + if (metadata.fileMetaData.hasExtraEmbeddings) { + this.setState({ activeCoordinates: metadata.cellMetaData.embeddings[0] }); + } else { + this.setState({ activeCoordinates: { id: -1, name: '' }}); + } + } + + setActiveCoordinates(evt, coords) { + BackendAPI.setActiveCoordinates(coords.value); + this.setState({ activeCoordinates: { id: coords.value, name: coords.text }}); } } diff --git a/scope-client/src/components/common/API.jsx b/scope-client/src/components/common/API.jsx index d5fa7aa5..f8348b1b 100644 --- a/scope-client/src/components/common/API.jsx +++ b/scope-client/src/components/common/API.jsx @@ -5,6 +5,7 @@ class API { this.loomFiles = []; this.activeLoom = null; + this.activeCoordinates = -1; this.activeLoomChangeListeners = []; this.features = { @@ -42,11 +43,14 @@ class API { return this.GBCConnection; } - getActiveLoom() { return this.activeLoom; } + getActiveCoordinates() { + return this.activeCoordinates; + } + getActiveLoomMetadata() { return this.loomFiles[this.activeLoom]; } @@ -62,9 +66,15 @@ class API { setActiveLoom(loom) { this.activeLoom = loom; - let file = this.loomFiles[this.activeLoom]; this.activeLoomChangeListeners.forEach((listener) => { - listener(this.activeLoom, file); + listener(this.activeLoom, this.activeCoordinates); + }) + } + + setActiveCoordinates(coords) { + this.activeCoordinates = coords; + this.activeLoomChangeListeners.forEach((listener) => { + listener(this.activeLoom, this.activeCoordinates); }) } diff --git a/scope-client/src/components/common/Viewer.jsx b/scope-client/src/components/common/Viewer.jsx index 61103895..e531bd01 100644 --- a/scope-client/src/components/common/Viewer.jsx +++ b/scope-client/src/components/common/Viewer.jsx @@ -59,7 +59,7 @@ export default class Viewer extends Component { BackendAPI.onViewerSelectionsChange(this.viewerSelectionListener); BackendAPI.onViewerTransformChange(this.viewerTransformListener); if (this.props.loomFile != null) { - this.getPoints(this.props.loomFile, () => { + this.getPoints(this.props.loomFile, this.props.activeCoordinates, () => { this.getFeatureColors(this.props.activeFeatures, this.props.loomFile, this.props.thresholds); }); } @@ -69,8 +69,8 @@ export default class Viewer extends Component { } componentWillReceiveProps(nextProps) { - if (this.props.loomFile != nextProps.loomFile) { - this.getPoints(nextProps.loomFile, () => { + if (this.props.loomFile != nextProps.loomFile || this.props.activeCoordinates != nextProps.activeCoordinates) { + this.getPoints(nextProps.loomFile, nextProps.activeCoordinates, () => { this.getFeatureColors(nextProps.activeFeatures, nextProps.loomFile, nextProps.thresholds); }); } else { @@ -323,16 +323,18 @@ export default class Viewer extends Component { } } - getPoints(loomFile, callback) { + getPoints(loomFile, coordinates, callback) { let query = { loomFilePath: loomFile, - coordinatesID: -1 + coordinatesID: parseInt(coordinates) }; + console.log('getPoints', query); this.startBenchmark("getPoints") BackendAPI.getConnection().then((gbc) => { gbc.services.scope.Main.getCoordinates(query, (err, response) => { // Update the coordinates and remove all previous data points if (response) { + console.log(response); this.container.removeChildren(); let c = { x: response.x, diff --git a/scope-client/src/components/pages/Expression.jsx b/scope-client/src/components/pages/Expression.jsx index fb170e29..7d34af2c 100644 --- a/scope-client/src/components/pages/Expression.jsx +++ b/scope-client/src/components/pages/Expression.jsx @@ -11,10 +11,12 @@ export default class Expression extends Component { super(); this.state = { activeLoom: BackendAPI.getActiveLoom(), + activeCoordinates: BackendAPI.getActiveCoordinates(), activeFeatures: BackendAPI.getActiveFeatures('gene') } - this.activeLoomListener = (loom) => { - this.setState({activeLoom: loom}); + this.activeLoomListener = (loom, coordinates) => { + console.log('loom change', loom, coordinates); + this.setState({activeLoom: loom, activeCoordinates: coordinates}); }; this.activeFeaturesListener = (features) => { this.setState({activeFeatures: features}); @@ -22,7 +24,7 @@ export default class Expression extends Component { } render() { - const { activeLoom, activeFeatures } = this.state; + const { activeLoom, activeFeatures, activeCoordinates } = this.state; return (
@@ -47,7 +49,7 @@ export default class Expression extends Component { - + diff --git a/scope-client/src/components/pages/Regulon.jsx b/scope-client/src/components/pages/Regulon.jsx index baced96a..ad60a417 100644 --- a/scope-client/src/components/pages/Regulon.jsx +++ b/scope-client/src/components/pages/Regulon.jsx @@ -14,13 +14,14 @@ export default class Regulon extends Component { super(); this.state = { activeLoom: BackendAPI.getActiveLoom(), + activeCoordinates: BackendAPI.getActiveCoordinates(), activeFeatures: BackendAPI.getActiveFeatures('regulon'), geneFeatures: this.getGeneFeatures(BackendAPI.getActiveFeatures('regulon')), thresholds: BackendAPI.getThresholds(), colors: ["red", "green", "blue"] }; - this.activeLoomListener = (loom) => { - this.setState({activeLoom: loom}); + this.activeLoomListener = (loom, coordinates) => { + this.setState({activeLoom: loom, activeCoordinates: coordinates}); }; this.activeFeaturesListener = (features, i) => { let thresholds = this.state.thresholds; @@ -31,7 +32,7 @@ export default class Regulon extends Component { } render() { - const { activeLoom, activeFeatures, thresholds, colors, geneFeatures } = this.state; + const { activeLoom, activeCoordinates, activeFeatures, thresholds, colors, geneFeatures } = this.state; let featureSearch = _.times(3, i => ( @@ -62,14 +63,14 @@ export default class Regulon extends Component { Regulon AUC values - + Cells passing thresholds - +

Expression levels - +
@@ -102,7 +103,6 @@ export default class Regulon extends Component { onThresholdChange(idx, threshold) { let thresholds = this.state.thresholds; - console.log('thresh', idx, threshold); thresholds[idx] = threshold; BackendAPI.setThresholds(thresholds); this.setState({thresholds: thresholds});