Skip to content

Commit 08c9438

Browse files
author
rodriguez-facundo
committed
#135 Split NetPyNEInstantiated component, add redux actions to simulate / instantiate
1 parent 1be0eef commit 08c9438

10 files changed

Lines changed: 353 additions & 225 deletions

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react'
2+
import Tooltip from '@material-ui/core/Tooltip'
3+
import { makeStyles } from '@material-ui/core/styles';
4+
5+
const tooltipStyle = makeStyles(({ palette, typography }) => ({
6+
arrow: { color: palette.common.black, },
7+
tooltip: { backgroundColor: palette.common.black, fontSize: typography.subtitle1.fontSize },
8+
}));
9+
10+
export default function CustomTooltip (props) {
11+
const classes = tooltipStyle();
12+
13+
return <Tooltip arrow classes={classes} {...props} />;
14+
}

webapp/components/index.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
maximizeWidget
1010
} from "../redux/actions/flexlayout";
1111
import { openBackendErrorDialog, closeBackendErrorDialog } from '../redux/actions/errors';
12-
import { updateCards, editModel, createNetwork, createAndSimulateNetwork, showNetwork, pythonCall } from "../redux/actions/general";
12+
import { updateCards, editModel, simulateNetwork, createNetwork, createAndSimulateNetwork, showNetwork, pythonCall } from "../redux/actions/general";
1313
import { closeDrawerDialogBox, openDrawerDialogBox } from '../redux/actions/drawer';
1414
import { newWidget } from "../redux/actions/flexlayout";
1515

@@ -187,10 +187,18 @@ export const NetPyNEInclude = connect(
187187

188188
import _NetPyNEInstantiated from "./instantiation/NetPyNEInstantiated"
189189
export const NetPyNEInstantiated = connect(
190-
null,
191-
dispatch => ({ newWidget: conf => dispatch(newWidget(conf)), })
190+
state => ({ modelState: state.general.modelState }),
191+
null
192192
)(_NetPyNEInstantiated)
193193

194+
import _NetWorkControlButtons from './instantiation/NetWorkControlButtons'
195+
export const NetWorkControlButtons = connect(
196+
state => ({ modelState: state.general.modelState }),
197+
dispatch => ({
198+
createAndSimulateNetwork: () => dispatch(createAndSimulateNetwork),
199+
simulateNetwork: () => dispatch(simulateNetwork),
200+
})
201+
)(_NetWorkControlButtons)
194202

195203
import _ActionDialog from './settings/actions/ActionDialog'
196204
export const ActionDialog = connect(
@@ -200,6 +208,17 @@ export const ActionDialog = connect(
200208
closeBackendErrorDialog: () => dispatch(closeBackendErrorDialog)
201209
})
202210
)(_ActionDialog)
211+
212+
213+
import _PlotButton from './instantiation/PlotButtons'
214+
export const PlotButtons = connect(
215+
state => ({ ...state.errors, openErrorDialogBox: state.errors.openDialog }),
216+
dispatch => ({
217+
newWidget: conf => dispatch(newWidget(conf)),
218+
closeBackendErrorDialog: () => dispatch(closeBackendErrorDialog),
219+
pythonCallErrorDialogBox: payload => dispatch(openBackendErrorDialog(payload))
220+
})
221+
)(_PlotButton)
203222
// ---------------------------------------------------------------------------------------- //
204223

205224
// DEFAULTS
@@ -209,4 +228,5 @@ export { default as NetPyNEAddNew } from "./general/NetPyNEAddNew";
209228
export { default as NetPyNEThumbnail } from "./general/NetPyNEThumbnail";
210229
export { default as NetPyNECoordsRange } from "./general/NetPyNECoordsRange";
211230
export { default as NetPyNESimConfig } from "./definition/configuration/NetPyNESimConfig";
212-
export { default as HTMLViewer } from './general/HTMLViewer'
231+
export { default as HTMLViewer } from './general/HTMLViewer'
232+
export { default as Tooltip } from './general/Tooltip'

webapp/components/instantiation/NetPyNEInstantiated.js

Lines changed: 16 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,21 @@
11
import React, { createRef } from 'react';
22
import ReactDOM from 'react-dom'
3-
import Dialog from '@material-ui/core/Dialog';
4-
import Button from '@material-ui/core/Button';
53
import Canvas from '@geppettoengine/geppetto-client/js/components/interface/3dCanvas/Canvas';
64
import ControlPanel from 'geppetto-client/js/components/interface/controlPanel/controlpanel';
75
import IconButton from '@geppettoengine/geppetto-client/js/components/controls/iconButton/IconButton';
8-
import Menu from '@material-ui/core/Menu';
9-
import MenuItem from '@material-ui/core/MenuItem';
10-
import Utils from '../../Utils';
6+
import { NetWorkControlButtons } from 'netpyne/components'
117

128

13-
import DialogActions from '@material-ui/core/DialogActions';
14-
import DialogContent from '@material-ui/core/DialogContent';
15-
import DialogContentText from '@material-ui/core/DialogContentText';
16-
import DialogTitle from '@material-ui/core/DialogTitle';
17-
189
const styles = {
1910
modal: {
2011
position: 'absolute !important',
2112
backgroundColor: 'rgba(0, 0, 0, 0.6)',
2213
zIndex: '999',
2314
height: '100%',
2415
width: '100%',
25-
top: 0
26-
},
27-
28-
menuItemDiv: {
29-
fontSize: '12px',
30-
lineHeight: '28px'
16+
overflow: 'hidden'
3117
},
3218

33-
menuItem: {
34-
lineHeight: '28px',
35-
minHeight: '28px'
36-
},
3719
instantiatedContainer: {
3820
height: '100%',
3921
width: '100%',
@@ -43,29 +25,7 @@ const styles = {
4325
left: 34,
4426
top: 280
4527
},
46-
plotBtn: {
47-
position: 'absolute',
48-
left: 34,
49-
top: 317
50-
}
51-
5228
};
53-
const plots = [
54-
{ id: 'connectionPlot', primaryText: 'Connectivity', plotName: 'Connections Plot', plotMethod: 'plotConn', plotType: false },
55-
{ id: '2dNetPlot', primaryText: '2D network', plotName: '2D Net Plot', plotMethod: 'plot2Dnet', plotType: false },
56-
{ id: 'shapePlot', primaryText: 'Cell shape', plotName: 'Shape Plot', plotMethod: 'plotShape', plotType: false },
57-
{ id: 'tracesPlot', primaryText: 'Cell traces', plotName: 'Traces Plot', plotMethod: 'plotTraces', plotType: false },
58-
{ id: 'rasterPlot', primaryText: 'Raster plot', plotName: 'Raster Plot', plotMethod: 'plotRaster', plotType: false },
59-
{ id: 'spikePlot', primaryText: 'Spike histogram', plotName: 'Spike Hist Plot', plotMethod: 'plotSpikeHist', plotType: false },
60-
{ id: 'spikeStatsPlot', primaryText: 'Spike stats', plotName: 'Spike Stats Plot', plotMethod: 'plotSpikeStats', plotType: false },
61-
{ id: 'ratePSDPlot', primaryText: 'Rate PSD', plotName: 'Rate PSD Plot', plotMethod: 'plotRatePSD', plotType: false },
62-
{ id: 'LFPTimeSeriesPlot', primaryText: 'LFP time-series', plotName: 'LFP Time Series Plot', plotMethod: 'plotLFP', plotType: 'timeSeries' },
63-
{ id: 'LFPLocationsPlot', primaryText: 'LFP PSD', plotName: 'LFP PSD Plot', plotMethod: 'plotLFP', plotType: 'PSD' },
64-
{ id: 'LFPSpectrogramPlot', primaryText: 'LFP spectrogram', plotName: 'LFP Spectrogram Plot', plotMethod: 'plotLFP', plotType: 'spectrogram' },
65-
{ id: 'LFPLocationsPlot', primaryText: 'LFP locations', plotName: 'LFP Locations Plot', plotMethod: 'plotLFP', plotType: 'locations' },
66-
{ id: 'grangerPlot', primaryText: 'Granger causality plot', plotName: 'Granger Plot', plotMethod: 'granger', plotType: false },
67-
{ id: 'rxdConcentrationPlot',primaryText: 'RxD concentration plot', plotName: 'RxD concentration plot', plotMethod: 'plotRxDConcentration', plotType: false }
68-
];
6929

7030
export default class NetPyNEInstantiated extends React.Component {
7131

@@ -74,106 +34,26 @@ export default class NetPyNEInstantiated extends React.Component {
7434
this.state = {
7535
model: props.model,
7636
controlPanelHidden: true,
77-
plotButtonOpen: false,
78-
openDialog: false,
7937
bringItToFront: 0,
8038
update: 0
8139
};
8240
this.dimensions = { width: 200, height: 200 }
83-
this.canvasRef = createRef();
84-
85-
86-
this.plotFigure = this.plotFigure.bind(this);
87-
this.newPlotWidget = this.newPlotWidget.bind(this);
88-
this.handleClick = this.handleClick.bind(this);
89-
this.handleRequestClose = this.handleRequestClose.bind(this);
41+
this.canvasRef = createRef();
9042
}
9143

9244
componentDidUpdate (){
9345
this.resizeIfNeeded()
9446
}
95-
96-
handleCloseDialog = () => {
97-
this.setState({ openDialog: false });
98-
};
99-
100-
newPlotWidget (name, svgResponse, data, i, total) {
101-
if (svgResponse === '') {
102-
return
103-
}
104-
const pathName = `network.${name.replace(/ /g, '')}_${i}`
105-
if (!window.plotSvgImages) {
106-
window.plotSvgImages = { [pathName]: svgResponse }
107-
} else {
108-
window.plotSvgImages[pathName] = svgResponse
109-
}
110-
111-
this.props.newWidget({
112-
path: pathName,
113-
component: 'Plot',
114-
panelName: 'topPanel'
115-
})
116-
117-
if (i < total) {
118-
this.newPlotWidget(name, data[i++], data, i++, total)
119-
}
120-
121-
if (i === total) {
122-
this.handleRequestClose()
123-
}
124-
}
125-
126-
processError (response, plotName) {
127-
var parsedResponse = Utils.getErrorResponse(response);
128-
if (parsedResponse) {
129-
this.setState({
130-
dialogTitle: "NetPyNE returned an error plotting " + plotName,
131-
dialogMessage: parsedResponse['message'] + "\n " + parsedResponse['details'],
132-
openDialog: true
133-
});
134-
return true;
135-
}
136-
return false;
137-
}
138-
139-
plotFigure (plotName, plotMethod, plotType = false) {
140-
Utils.evalPythonMessage('netpyne_geppetto.getPlot', [plotMethod, plotType], false)
141-
.then(response => {
142-
// TODO Fix this, use just JSON
143-
if (typeof response === 'string'){
144-
if (response.startsWith("{") && response.endsWith("}")) {
145-
if (this.processError(response, plotName)){
146-
return;
147-
}
148-
}
149-
if (response.startsWith("[") && response.endsWith("]")) {
150-
response = eval(response);
151-
}
152-
}
153-
if ($.isArray(response)) {
154-
this.newPlotWidget(plotName, response[0], response, 0, response.length - 1);
155-
} else if (response == -1) {
156-
this.processError(response, plotName)
157-
} else {
158-
this.newPlotWidget(plotName, response, response, 0, 0);
159-
}
160-
});
161-
}
16247

16348

16449
componentDidMount () {
16550
this.canvasRef.current.engine.setLinesThreshold(10000);
16651
this.canvasRef.current.displayAllInstances();
167-
if (Instances.length > 2) {
168-
// update canvas only if there are instances to show
169-
this.canvasRef.current.engine.updateSceneWithNewInstances(window.Instances);
170-
}
171-
17252
this.canvasRef.current.setBackgroundColor('#191919')
173-
53+
17454
window.addEventListener('resize', this.delayedResize.bind(this))
17555
this.resizeIfNeeded()
176-
56+
this.updateInstances()
17757

17858
GEPPETTO.on(GEPPETTO.Events.Control_panel_close, () => {
17959
this.setState({ bringItToFront: 0 })
@@ -186,22 +66,11 @@ export default class NetPyNEInstantiated extends React.Component {
18666
window.removeEventListener('resize', this.delayedResize)
18767
}
18868

189-
handleClick (event) {
190-
// This prevents ghost click.
191-
event.preventDefault();
192-
193-
this.setState({
194-
plotButtonOpen: true,
195-
anchorEl: event.currentTarget,
196-
});
197-
}
198-
199-
handleRequestClose () {
200-
this.setState({ plotButtonOpen: false, });
201-
}
202-
20369
updateInstances () {
204-
this.canvasRef.current.engine.updateSceneWithNewInstances(window.Instances);
70+
if (Instances.network) {
71+
// update canvas only if there are instances to show
72+
this.canvasRef.current.engine.updateSceneWithNewInstances(window.Instances);
73+
}
20574
}
20675

20776
resizeCanvas () {
@@ -252,80 +121,18 @@ export default class NetPyNEInstantiated extends React.Component {
252121
>
253122
</ControlPanel>
254123
</div>
124+
255125
<IconButton style={styles.controlpanelBtn}
256126
onClick={() => {
257-
$('#controlpanel').show(); this.setState({ bringItToFront: 1 })
127+
$('#controlpanel').show()
128+
this.setState({ bringItToFront: 1 })
258129
}}
259130
icon={"fa-list"}
260-
id="ControlPanelButton" />
261-
<div>
262-
<IconButton
263-
onClick={this.handleClick}
264-
style={styles.plotBtn}
265-
label="Plot"
266-
icon="fa-bar-chart"
267-
id="PlotButton"
268-
/>
269-
<Menu
270-
open={this.state.plotButtonOpen}
271-
onClose={this.handleRequestClose}
272-
anchorEl={this.state.anchorEl}
273-
>
274-
{plots.map((plot, index) => (
275-
<MenuItem
276-
id={plot.id}
277-
key={index}
278-
style={styles.menuItem}
279-
onClick={() => this.plotFigure(plot.plotName, plot.plotMethod, plot.plotType)}
280-
>
281-
{plot.primaryText}
282-
</MenuItem>
283-
))}
284-
</Menu>
285-
</div>
286-
287-
288-
<IconButton
289-
color='secondary'
290-
id={"refreshInstanciatedNetworkButton"}
291-
key={"refreshInstanceButton"}
292-
icon="fa-refresh"
293-
onClick={() => this.instantiate({ usePrevInst: false })}
294-
style={{ position: 'absolute', right: 30, top: 80, zIndex: 1 }}
295-
tooltip-data={this.props.freezeInstance ? "Your network is in sync" : "Synchronise network"}
296-
disabled={!!this.props.freezeInstance}
297-
/>
298-
299-
300-
<IconButton
301-
color='secondary'
302-
id={"launchSimulationButton"}
303-
icon="fa-rocket"
304-
onClick={() => this.setState({ openDialog: true })}
305-
style={{ position: 'absolute', right: 30, top: 120, zIndex: 1 }}
306-
tooltip-data={this.props.freezeSimulation ? "You have already simulated your network" : "Simulate your network"}
307-
disabled={!!this.props.freezeSimulation}
131+
id="ControlPanelButton"
308132
/>
309-
310-
<Dialog
311-
open={this.state.openDialog}
312-
onClose={this.handleCloseDialog}
313-
style={{ whiteSpace: "pre-wrap" }}
314-
>
315-
<DialogTitle>{this.state.dialogTitle}</DialogTitle>
316-
<DialogContent>
317-
<DialogContentText>
318-
{this.state.dialogMessage}
319-
</DialogContentText>
320-
</DialogContent>
321-
<DialogActions>
322-
<Button
323-
id="netPyneDialog"
324-
color="primary"
325-
onClick={this.handleCloseDialog}
326-
>Ok</Button>
327-
</DialogActions>
328-
</Dialog>
133+
134+
<NetWorkControlButtons/>
135+
329136
</div>
330137

331138
);

0 commit comments

Comments
 (0)