Skip to content

Commit 722e2bf

Browse files
Merge pull request #504 from MetaCell/feature/483
Feature/483
2 parents 5105237 + a5d3e44 commit 722e2bf

File tree

16 files changed

+499
-123
lines changed

16 files changed

+499
-123
lines changed

Dockerfile

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@ FROM frodriguez4600/jupyter-neuron:v7.8.0
22
ARG INSTALLATION_FOLDER=/home/jovyan/work/NetPyNE-UI
33
ARG NETPYNE_VERSION=development
44
ARG WORKSPACE_VERSION=nov2020
5-
ARG JUPYTER_GEPPETTO_VERSION=development
6-
ARG PYGEPPETTO_VERSION=development
5+
ARG GEPPETTO_VERSION=development
76
ARG BUILD_ARGS=""
87

98
USER $NB_USER
109

1110
ENV INSTALLATION_FOLDER=$INSTALLATION_FOLDER
1211
ENV NETPYNE_VERSION=$NETPYNE_VERSION
1312
ENV WORKSPACE_VERSION=$WORKSPACE_VERSION
14-
ENV JUPYTER_GEPPETTO_VERSION=$JUPYTER_GEPPETTO_VERSION
15-
ENV PYGEPPETTO_VERSION=$PYGEPPETTO_VERSION
13+
ENV GEPPETTO_VERSION=$GEPPETTO_VERSION
1614
ENV BUILD_ARGS=$BUILD_ARGS
1715

1816
# Install openmpi for parallel simulations
@@ -30,10 +28,12 @@ RUN pip install -r requirements.txt
3028
COPY --chown=1000:1000 . .
3129
WORKDIR ${INSTALLATION_FOLDER}/utilities
3230

33-
RUN python install.py ${BUILD_ARGS}
31+
RUN npm install --global yarn
32+
RUN npm install --global yalc
33+
RUN python install.py ${BUILD_ARGS} --geppetto ${GEPPETTO_VERSION}
3434

3535
WORKDIR ${INSTALLATION_FOLDER}
3636

3737
RUN pip install -r requirements-test.txt
38-
RUN pytest tests/backend
38+
# RUN pytest tests/backend
3939
CMD /bin/bash -c "jupyter notebook --NotebookApp.default_url=/geppetto --NotebookApp.token='' --library=netpyne_ui --NotebookApp.disable_check_xsrf=True"

netpyne_ui/netpyne_geppetto.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -887,16 +887,18 @@ def deleteParam(self, model, label):
887887
# side effect on other rules
888888
if "popParams" in model:
889889
self.propagate_field_rename("pop", None, label)
890-
self.propagate_field_rename("cellModel", None, rule['cellModel'])
891-
self.propagate_field_rename("cellType", None, rule['cellType'])
890+
if 'cellModel' in rule:
891+
self.propagate_field_rename("cellModel", None, rule['cellModel'])
892+
if 'cellType' in rule:
893+
self.propagate_field_rename("cellType", None, rule['cellType'])
892894

893895
elif "stimSourceParams" in model:
894896

895897
self.propagate_field_rename("source", None, label)
896898
elif "synMechParams" in model:
897899
self.propagate_field_rename("synMech", None, label)
898900
return True
899-
except Exception:
901+
except Exception as e :
900902
logging.exception(f"Error while deleting parameter: {label}")
901903
return False
902904

@@ -974,7 +976,7 @@ def propagate(self, model, label, cond, new, old):
974976
for plot in analysis.keys():
975977
if cond in analysis[plot].keys():
976978
for index, item in enumerate(analysis[plot][cond]):
977-
if isinstance(item, str):
979+
if isinstance(item, str) or isinstance(item, int):
978980
if item == old:
979981
if new == None:
980982
analysis[plot][cond].remove(item)
@@ -992,11 +994,11 @@ def propagate(self, model, label, cond, new, old):
992994
else:
993995
obj = getattr(self.netParams, model)
994996
for key in obj.keys():
995-
if label in list(obj[key][cond].keys()):
997+
if cond in obj[key] and label in list(obj[key][cond].keys()):
996998
if isinstance(obj[key][cond][label], str):
997999
if old == obj[key][cond][label]:
9981000
if new == '' or new == None:
999-
obj[key].pop(label)
1001+
obj[key][cond].pop(label)
10001002
else:
10011003
obj[key][cond][label] = new
10021004
elif isinstance(obj[key][cond][label], list):

utilities/install.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,10 @@ def main(netpyne_branch, workspace_branch, geppetto_branch=None, skipNpm=False,
194194
if development:
195195
# install geppetto meta
196196
if os.path.exists(os.path.join(WEBAPP_DIR, '.yalc')):
197-
execute(cmd=['ln', '-s', os.path.expanduser('~') + '/.yalc', '.yalc'], cwd=WEBAPP_DIR)
197+
execute(cmd=['rm', '-rf', '.yalc'], cwd=WEBAPP_DIR)
198+
execute(cmd=['ln', '-s', os.path.expanduser('~') + '/.yalc', '.yalc'], cwd=WEBAPP_DIR)
199+
else:
200+
execute(cmd=['ln', '-s', os.path.expanduser('~') + '/.yalc', '.yalc'], cwd=WEBAPP_DIR)
198201
execute(cmd=['ls'], cwd=WEBAPP_DIR)
199202
execute(cmd=['bash', 'geppetto_ui.sh'], cwd=WEBAPP_DIR)
200203
execute(cmd=['yarn'], cwd=WEBAPP_DIR)

webapp/Utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const Utils = {
6161
}
6262

6363
// skip the list element, e.g. "E"!
64-
console.debug(`Skip ${item} at ${nextObject.label}`);
64+
// console.debug(`Skip ${item} at ${nextObject.label}`);
6565
skipped = true;
6666
} else {
6767
skipped = false;

webapp/components/NetPyNE.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const styles = ({ zIndex }) => ({
3131
},
3232
topbar: {
3333
position: 'relative',
34-
zIndex: zIndex.drawer + 1,
34+
zIndex: zIndex.drawer,
3535
},
3636
content: {
3737
flexGrow: 1,
@@ -46,6 +46,11 @@ const TIMEOUT = 10000;
4646
const EXPERIMENT_POLL_INTERVAL = 1000;
4747

4848
class NetPyNE extends React.Component {
49+
constructor (props) {
50+
super(props);
51+
this.openPythonCallDialog = this.openPythonCallDialog.bind(this);
52+
}
53+
4954
componentDidMount () {
5055
GEPPETTO.on(GEPPETTO.Events.Error_while_exec_python_command, this.openPythonCallDialog, this);
5156

webapp/components/experiments/ExperimentEdit.js

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import ParameterMenu from './ParameterMenu';
2626
import useStyles from './ExperimentEditStyle';
2727
import * as ExperimentHelper from './ExperimentHelper';
2828
import DialogBox from '../general/DialogBox';
29+
import workerCode from './workers/processExperimentData';
30+
2931
const RANGE_VALUE = 0;
3032
const SUPPORTED_TYPES = [REAL_TYPE.INT, REAL_TYPE.FLOAT, REAL_TYPE.STR, REAL_TYPE.BOOL];
3133
const MAX_TRIALS = 100;
@@ -191,13 +193,13 @@ const ExperimentEdit = (props) => {
191193
const [experimentNameError, setExperimentNameError] = useState('');
192194
const [selectionParams, setSelectionParams] = useState([]);
193195
const [trialNumberErrorDialogOpen, setTrialNumberErrorDialogOpen] = useState({ condition: false, number: 1 });
196+
const [paramsCounter, setParamsCounter] = useState(0);
194197

195198
// Existing Experiment.
196199
const [experiment, setExperiment] = useState(null);
197200
const experiments = useSelector((state) => state.experiments.experiments);
198201

199202
let numberOfTrials = 1;
200-
// const dispatch = useDispatch();
201203
const validateParameter = (param) => {
202204
let updatedParam = param;
203205
if (param.type === LIST) {
@@ -253,20 +255,20 @@ const ExperimentEdit = (props) => {
253255
const getParameters = () => {
254256
ExperimentsApi.getParameters()
255257
.then((params) => {
256-
const flattened = Utils.flatten(params);
257-
const paramKeys = Object.keys(flattened);
258-
259-
const filteredKeys = paramKeys.filter((key) => {
260-
// TODO: avoid to fetch field twice!
261-
const field = Utils.getMetadataField(`netParams.${key}`);
262-
if (field && SUPPORTED_TYPES.includes(field.type)) {
263-
return true;
258+
// eslint-disable-next-line prefer-template
259+
// eslint-disable-next-line no-undef
260+
const worker = new Worker(workerCode);
261+
worker.onmessage = function (e) {
262+
switch (e.data.resultMessage) {
263+
case 'OK':
264+
setSelectionParams(e.data.params.results);
265+
worker.terminate();
266+
break;
267+
default:
268+
console.error('worker processing metadata for autocomplete not working.');
264269
}
265-
return false;
266-
});
267-
268-
console.debug(`Size before ${paramKeys.length}, after: ${filteredKeys.length}`);
269-
setSelectionParams(filteredKeys);
270+
};
271+
worker.postMessage({ message: 'process', params: { data: params, metadata: window.metadata } });
270272
});
271273
};
272274

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
const workerCode = () => {
2+
// eslint-disable-next-line no-undef
3+
self.onmessage = function (event) {
4+
// The object that the web page sent is stored in the event.data property.
5+
const Utils = {
6+
getMetadataField (key, field = null) {
7+
if (key === undefined) {
8+
return null;
9+
}
10+
11+
let currentObject;
12+
let nextObject = event.data.params.metadata;
13+
let skipped = false;
14+
15+
// eslint-disable-next-line no-restricted-syntax
16+
key.split('.').forEach((item) => {
17+
if (
18+
currentObject != null
19+
&& currentObject?.container === true
20+
&& !(item in nextObject)
21+
) {
22+
if (skipped) {
23+
return null;
24+
}
25+
26+
// skip the list element, e.g. "E"!
27+
// console.debug(`Skip ${item} at ${nextObject.label}`);
28+
skipped = true;
29+
} else {
30+
skipped = false;
31+
32+
if (item in nextObject) {
33+
currentObject = nextObject[item];
34+
if ('children' in currentObject) {
35+
nextObject = currentObject.children;
36+
}
37+
} else {
38+
currentObject = null;
39+
}
40+
}
41+
});
42+
43+
if (currentObject) {
44+
return field ? currentObject[field] : currentObject;
45+
}
46+
47+
return null;
48+
},
49+
50+
flatten (obj, path = '') {
51+
if (!(obj instanceof Object)) {
52+
// eslint-disable-next-line no-new-object
53+
const newObj = new Object();
54+
newObj[path.replace(/\.$/g, '')] = obj;
55+
return newObj;
56+
}
57+
58+
return Object.keys(obj).reduce(
59+
(output, key) => (obj instanceof Array
60+
? Object.assign(output, Utils.flatten(obj[key], `${path}[${key}].`))
61+
: Object.assign(output, Utils.flatten(obj[key], `${path + key}.`))),
62+
{},
63+
);
64+
},
65+
};
66+
67+
const REAL_TYPE = {
68+
INT: 'int',
69+
FLOAT: 'float',
70+
BOOL: 'bool',
71+
STR: 'str',
72+
FUNC: 'func',
73+
DICT: 'dict',
74+
DICT_DICT: 'dict(dict)',
75+
};
76+
const SUPPORTED_TYPES = [
77+
REAL_TYPE.INT,
78+
REAL_TYPE.FLOAT,
79+
REAL_TYPE.STR,
80+
REAL_TYPE.BOOL,
81+
];
82+
const { data } = event.data.params;
83+
const flattened = Utils.flatten(data);
84+
const paramKeys = Object.keys(flattened);
85+
const filteredKeys = paramKeys.filter((key) => {
86+
// TODO: avoid to fetch field twice!
87+
const field = Utils.getMetadataField(`netParams.${key}`);
88+
if (field && SUPPORTED_TYPES.includes(field.type)) {
89+
return true;
90+
}
91+
return false;
92+
});
93+
94+
// eslint-disable-next-line no-undef
95+
postMessage({ resultMessage: 'OK', params: { results: filteredKeys } });
96+
};
97+
};
98+
99+
let code = workerCode.toString();
100+
code = code.substring(code.indexOf('{') + 1, code.lastIndexOf('}'));
101+
102+
const blob = new Blob([code], { type: 'application/javascript' });
103+
const workerScript = window.URL.createObjectURL(blob);
104+
105+
export default workerScript;

0 commit comments

Comments
 (0)