Skip to content

Commit ba52bd5

Browse files
authored
Merge pull request #801 from MetaCell/feature/199
Feature/199 - Population cell list
2 parents dd70fa6 + 58dcfe8 commit ba52bd5

4 files changed

Lines changed: 140 additions & 65 deletions

File tree

webapp/components/definition/populations/Dimensions.js

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import Box from '@material-ui/core/Box';
66

77
import InputLabel from '@material-ui/core/InputLabel';
88
import FormControl from '@material-ui/core/FormControl';
9-
109
import {
1110
NetPyNEField,
11+
ListComponent,
1212
NetPyNETextField,
1313
} from 'netpyne/components';
1414
import Utils from '../../../Utils';
@@ -44,6 +44,10 @@ class DimensionsComponent extends Component {
4444
label: 'Grid spacing',
4545
value: 'gridSpacing',
4646
},
47+
{
48+
label: 'Cell List',
49+
value: 'cellsList',
50+
},
4751
];
4852
}
4953

@@ -52,7 +56,6 @@ class DimensionsComponent extends Component {
5256
this.updateLayout();
5357
}
5458
}
55-
5659
componentWillUnmount () {
5760
this.mounted = false;
5861
}
@@ -108,6 +111,7 @@ class DimensionsComponent extends Component {
108111

109112
render () {
110113
const { classes } = this.props;
114+
111115
return (
112116
<div>
113117
<NetPyNEField id="netParams.popParams.numCells" className={classes.selectField}>
@@ -139,22 +143,29 @@ class DimensionsComponent extends Component {
139143
this.state.dimension != undefined && this.state.dimension != ''
140144
&& (
141145
<Box ml={1}>
142-
<NetPyNEField
143-
id={`netParams.popParams.${this.state.dimension}`}
144-
className={classes.fields}
145-
>
146-
<NetPyNETextField
147-
fullWidth
148-
variant="filled"
149-
handleChange={this.handleDimValueChange}
146+
{this.state.dimension === 'cellsList' ? (
147+
<ListComponent
150148
model={`netParams.popParams['${this.state.modelName}']['${this.state.dimension}']`}
151-
modelName={this.state.modelName}
152-
dimensionType={this.state.dimension}
153-
callback={(newValue, oldValue) => {
154-
this.props.updateCards();
155-
}}
149+
realType="list(dict)"
156150
/>
157-
</NetPyNEField>
151+
) : (
152+
<NetPyNEField
153+
id={`netParams.popParams.${this.state.dimension}`}
154+
className={classes.fields}
155+
>
156+
<NetPyNETextField
157+
fullWidth
158+
variant="filled"
159+
handleChange={this.handleDimValueChange}
160+
model={`netParams.popParams['${this.state.modelName}']['${this.state.dimension}']`}
161+
modelName={this.state.modelName}
162+
dimensionType={this.state.dimension}
163+
callback={(newValue, oldValue) => {
164+
this.props.updateCards();
165+
}}
166+
/>
167+
</NetPyNEField>
168+
)}
158169
</Box>
159170
)
160171
}

webapp/components/definition/populations/NetPyNEPopulation.js

Lines changed: 33 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const styles = ({ spacing }) => ({
3636
marginTop: spacing(3),
3737
width: '100%',
3838
},
39-
} );
39+
});
4040

4141
const { textColor, primaryColor, experimentLabelColor } = vars;
4242
const newPulseObject = {
@@ -47,7 +47,7 @@ const newPulseObject = {
4747
};
4848

4949
class NetPyNEPopulation extends React.Component {
50-
constructor (props) {
50+
constructor(props) {
5151
super(props);
5252
this.state = {
5353
currentName: props.name,
@@ -66,10 +66,10 @@ class NetPyNEPopulation extends React.Component {
6666
const name = componentName ? componentName : this.props.name;
6767
const command = `utils.convertToJS(netpyne_geppetto.netParams.popParams['${name}'])`
6868
const response = await execPythonMessage(command)
69-
this.setState({model: response})
69+
this.setState({ model: response })
7070
}
7171

72-
UNSAFE_componentWillReceiveProps (nextProps) {
72+
UNSAFE_componentWillReceiveProps(nextProps) {
7373
this.setState({
7474
currentName: nextProps.name,
7575
selectedIndex: 0,
@@ -78,7 +78,7 @@ class NetPyNEPopulation extends React.Component {
7878
this.updateModel(nextProps.name)
7979
}
8080

81-
shouldComponentUpdate (nextProps, nextState) {
81+
shouldComponentUpdate(nextProps, nextState) {
8282
return (
8383
this.state.model == undefined
8484
|| this.state.currentName != nextState.currentName
@@ -127,15 +127,6 @@ class NetPyNEPopulation extends React.Component {
127127
/>,
128128
);
129129
}
130-
modelParameters.push(
131-
<BottomNavigationAction
132-
key="CellList"
133-
label="Cell List"
134-
icon={<FontIcon className="fa fa-list" />}
135-
onClick={() => select(3, 'CellList')}
136-
/>,
137-
);
138-
139130
modelParameters.push(
140131
<BottomNavigationAction
141132
key="Stimulation"
@@ -177,15 +168,15 @@ class NetPyNEPopulation extends React.Component {
177168
}
178169
};
179170

180-
triggerUpdate (updateMethod) {
171+
triggerUpdate(updateMethod) {
181172
// common strategy when triggering processing of a value change, delay it, every time there is a change we reset
182173
if (this.updateTimer != undefined) {
183174
clearTimeout(this.updateTimer);
184175
}
185176
this.updateTimer = setTimeout(updateMethod, 1000);
186177
}
187178

188-
postProcessMenuItems (pythonData, selected) {
179+
postProcessMenuItems(pythonData, selected) {
189180
return pythonData.map((name) => (
190181
<MenuItem
191182
id={`${name}MenuItem`}
@@ -215,7 +206,7 @@ netpyne_geppetto.netParams.popParams['${this.props.name}']['spikePattern']['type
215206
}
216207

217208
handleStartMaxChange = (newValue) => {
218-
const maxIsSet = !( !newValue || newValue === '' )
209+
const maxIsSet = !(!newValue || newValue === '')
219210
if (maxIsSet) {
220211
const command = `
221212
pattern = netpyne_geppetto.netParams.popParams['${this.props.name}']['spikePattern']
@@ -236,16 +227,16 @@ del pattern['startMin']`
236227

237228
rhythmicLayout = () => {
238229
return <>
239-
<Box display='flex' alignItems='center' style={ { gap: '1rem' } }>
240-
<Typography style={ { color: experimentLabelColor, fontSize: '0.875rem', paddingLeft: '0.625rem', lineHeight: '130%', fontWeight: 400 } }>Start</Typography>
230+
<Box display='flex' alignItems='center' style={{ gap: '1rem' }}>
231+
<Typography style={{ color: experimentLabelColor, fontSize: '0.875rem', paddingLeft: '0.625rem', lineHeight: '130%', fontWeight: 400 }}>Start</Typography>
241232
<Grid container alignItems='center' spacing={1}>
242233
<Grid item xs={4}>
243234
<NetPyNEField mb={0} id="netParams.popParams.spikePattern.rhythmic.start">
244235
<NetPyNETextField
245-
fullWidth
246-
variant="filled"
247-
model={`netParams.popParams['${this.props.name}']['spikePattern']['${this.state.startParam}']`}
248-
/>
236+
fullWidth
237+
variant="filled"
238+
model={`netParams.popParams['${this.props.name}']['spikePattern']['${this.state.startParam}']`}
239+
/>
249240
</NetPyNEField>
250241
</Grid>
251242
<Grid item xs={4}>
@@ -288,7 +279,7 @@ del pattern['startMin']`
288279

289280
<NetPyNEField mb={0} id="netParams.popParams.spikePattern.rhythmic.distribution">
290281
<NetPyNESelectField
291-
style={{mb: 0}}
282+
style={{ mb: 0 }}
292283
method="netpyne_geppetto.getAvailableStimulationDistribution"
293284
model={
294285
`netParams.popParams['${this.props.name}']['spikePattern']['distribution']`
@@ -424,7 +415,7 @@ netpyne_geppetto.netParams.popParams['${this.props.name}']['pulses'].pop(${index
424415
execPythonMessage(command).then((_) => {
425416
this.updateModel()
426417
})
427-
}
418+
}
428419

429420
displayPulses = () => {
430421
if (!this.state.model || !this.state.model.pulses) {
@@ -434,7 +425,7 @@ netpyne_geppetto.netParams.popParams['${this.props.name}']['pulses'].pop(${index
434425
<Grid container alignItems='center' spacing={1} key={`pulse_${index}`}>
435426
<Tooltip title="Delete pulse" placement="top">
436427
<IconButton size="small" onClick={() => this.removePulse(index)}>
437-
<Icon fontSize="inherit" style={ { color: primaryColor } } className="fa fa-trash-o" />
428+
<Icon fontSize="inherit" style={{ color: primaryColor }} className="fa fa-trash-o" />
438429
</IconButton>
439430
</Tooltip>
440431
<Grid item xs={3}>
@@ -497,30 +488,30 @@ netpyne_geppetto.netParams.popParams['${this.props.name}']['pulses'].pop(${index
497488
/>
498489
</NetPyNEField>
499490
<NetPyNEField
500-
id="netParams.popParams.spkTimes"
501-
className="listStyle"
502-
>
491+
id="netParams.popParams.spkTimes"
492+
className="listStyle"
493+
>
503494
<ListComponent
504495
model={`netParams.popParams['${this.props.name}']['spkTimes']`}
505496
/>
506497
</NetPyNEField>
507-
<Box display='flex' alignItems='flex-start' style={{gap: '1rem'}}>
508-
<Typography style={ {
509-
color: experimentLabelColor, flexShrink: 0, padding: '18.5px 0 18.5px 10px', fontSize: '0.875rem', lineHeight: '130%', fontWeight: 400
510-
} }
498+
<Box display='flex' alignItems='flex-start' style={{ gap: '1rem' }}>
499+
<Typography style={{
500+
color: experimentLabelColor, flexShrink: 0, padding: '18.5px 0 18.5px 10px', fontSize: '0.875rem', lineHeight: '130%', fontWeight: 400
501+
}}
511502
>
512503
Spiking Pulse
513504
</Typography>
514-
<Box display='flex' flexDirection='column' style={{gap: '0.5rem'}}>
515-
{ this.displayPulses() }
505+
<Box display='flex' flexDirection='column' style={{ gap: '0.5rem' }}>
506+
{this.displayPulses()}
516507
</Box>
517508
</Box>
518509

519510
<Box pl={1.25}>
520511
<Button
521512
className='noHover'
522513
disableRipple
523-
style={ { color: primaryColor, padding: 0, textTransform: 'uppercase', fontSize: '0.75rem', letterSpacing: '0.01rem', lineHeight: '200%' } }
514+
style={{ color: primaryColor, padding: 0, textTransform: 'uppercase', fontSize: '0.75rem', letterSpacing: '0.01rem', lineHeight: '200%' }}
524515
variant='text'
525516
onClick={() => this.addAnotherPulse()}
526517
>+ add another pulse</Button>
@@ -545,7 +536,7 @@ netpyne_geppetto.netParams.popParams['${this.props.name}']['pulses'].pop(${index
545536

546537
<NetPyNEField mb={0} id="netParams.popParams.spikePattern">
547538
<NetPyNESelectField
548-
style={{mb: 0}}
539+
style={{ mb: 0 }}
549540
method="netpyne_geppetto.getAvailableStimulationPattern"
550541
model={
551542
`netParams.popParams['${this.props.name}']['spikePattern']['type']`
@@ -558,10 +549,10 @@ netpyne_geppetto.netParams.popParams['${this.props.name}']['pulses'].pop(${index
558549
{this.changeStimulationPatternLayout(this.state.model?.spikePattern?.type)}
559550

560551

561-
</>
552+
</>
562553
}
563554

564-
render () {
555+
render() {
565556

566557
const { classes } = this.props;
567558

@@ -673,13 +664,9 @@ netpyne_geppetto.netParams.popParams['${this.props.name}']['pulses'].pop(${index
673664
/>
674665
</Box>
675666
);
676-
} else if (this.state.sectionId == 'CellList') {
677-
var content = (
678-
<div>Option to provide individual list of cells. Coming soon ...</div>
679-
);
680667
} else if (this.state.sectionId == 'Stimulation') {
681668
var content = (
682-
<Box className="scrollbar scrollchild" mt={ 1 }>
669+
<Box className="scrollbar scrollchild" mt={1}>
683670
{/* <Box mb={ 3.5 } display='flex' style={ { gap: '0.5rem' } }>
684671
<Box>
685672
<Switch checked={true} />
@@ -707,10 +694,10 @@ netpyne_geppetto.netParams.popParams['${this.props.name}']['pulses'].pop(${index
707694
>View Configurations in stim. source</Button>
708695
</Box>
709696
</Box> */}
710-
<Box display='flex' flexDirection='column' style={ { gap: '0.5rem' } }>
697+
<Box display='flex' flexDirection='column' style={{ gap: '0.5rem' }}>
711698
<NetPyNEField mb={0} id="netParams.popParams.cellModel">
712699
<NetPyNESelectField
713-
style={{mb: 0}}
700+
style={{ mb: 0 }}
714701
method="netpyne_geppetto.getAvailableCellModels"
715702
model={
716703
`netParams.popParams['${this.props.name}']['cellModel']`

webapp/components/general/ControlPanelTreeItem.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ const ControlPanelTreeItem = (props) => {
325325
event.preventDefault();
326326
setShowColorPicker(true)
327327
}}>
328-
<SquareIcon fillColor={getColor(nodeId).hex}/>
328+
<SquareIcon fillColor={getColor(nodeId)?.hex}/>
329329

330330
</IconButton>
331331
{showColorPicker && isHoveredOver

0 commit comments

Comments
 (0)