Skip to content

Commit b701053

Browse files
committed
Merge branch 'development' of https://github.com/metacell/netpyne-ui into feature/depandabot_20231030
2 parents 5e2bb2b + dd70fa6 commit b701053

47 files changed

Lines changed: 2919 additions & 1358 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Dockerfile

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,83 @@
1-
FROM node:14.21.3-bullseye as jsbuild
1+
FROM node:14 as jsbuild
22

3-
WORKDIR /app
4-
5-
COPY --chown=1000:1000 webapp/package.json .
6-
COPY --chown=1000:1000 webapp/yarn.lock .
3+
ENV FOLDER=netpyne
74

5+
WORKDIR $FOLDER/webapp
6+
COPY webapp/package.json .
7+
COPY webapp/yarn.lock .
88

99
RUN yarn install --network-timeout 1000000000
1010

11-
COPY webapp/ .
11+
COPY webapp .
1212
RUN yarn build-dev
1313

14-
15-
RUN rm -Rf node_modules/*
16-
1714
###
1815
FROM jupyter/base-notebook:hub-1.5.0
1916
ENV NB_UID=jovyan
2017
ENV FOLDER=netpyne
21-
ARG BUILD_ARGS=""
22-
ARG WORKSPACE_VERSION=master
23-
# ARG GEPPETTO_VERSION=development
24-
# ARG NETPYNE_VERSION=master
25-
26-
ENV FOLDER=/home/jovyan/work/NetPyNE-UI
18+
ENV NP_LFPYKIT_HEAD_FILE=/home/jovyan/nyhead.mat
2719

2820
USER root
2921

3022
RUN rm -rf /var/lib/apt/lists
3123
RUN apt-get update -qq &&\
32-
apt-get install python3-tk vim nano unzip git make libtool g++ -qq pkg-config libfreetype6-dev libpng-dev libopenmpi-dev openjdk-11-jre-headless -y -y
24+
apt-get install python3-tk vim nano unzip git make libtool g++ -qq pkg-config libfreetype6-dev libpng-dev libopenmpi-dev -y
25+
RUN apt-get install openjdk-11-jre-headless -y
3326
RUN conda install python=3.7 -y
3427

28+
3529
WORKDIR $FOLDER
36-
COPY --chown=1000:1000 requirements.txt requirements.txt
37-
RUN --mount=type=cache,target=/root/.cache python -m pip install --upgrade pip && pip install -r requirements.txt --prefer-binary
30+
COPY --chown=1000:1000 requirements.txt requirements.txt
31+
RUN --mount=type=cache,target=/root/.cache python -m pip install --upgrade pip &&\
32+
pip install -r requirements.txt --prefer-binary
3833

39-
COPY --chown=jovyan:1000 . .
40-
COPY --from=jsbuild --chown=jovyan:1000 /app webapp
34+
COPY . .
35+
COPY --from=jsbuild --chown=1000:1000 $FOLDER/webapp/build webapp/build
4136

37+
# ToDo: fixme, for now remove the jupyter hub config json file because it overrides the default
38+
# and thus removes the frame ancestor cors settings
39+
RUN rm -f ~/.jupyter/*.json
40+
RUN chown $NB_UID .
41+
RUN chown $NB_UID /opt
42+
RUN rm -Rf workspace
43+
44+
USER $NB_UID
45+
46+
# sym link workspace pvc to $FOLDER
47+
RUN mkdir -p /opt/workspace
48+
RUN mkdir -p /opt/user
49+
50+
51+
ENV NEURON_HOME=/opt/conda
52+
53+
54+
USER root
4255

4356
RUN jupyter nbextension install --py --symlink --sys-prefix jupyter_geppetto
4457
RUN jupyter nbextension enable --py --sys-prefix jupyter_geppetto
4558
RUN jupyter nbextension enable --py --sys-prefix widgetsnbextension
4659
RUN jupyter serverextension enable --py --sys-prefix jupyter_geppetto
4760

48-
RUN python utilities/install.py ${BUILD_ARGS} --workspace $WORKSPACE_VERSION
61+
ARG BUILD_ARGS=""
62+
ARG WORKSPACE_VERSION=master
63+
RUN --mount=type=cache,target=/root/.cache python -m pip install --upgrade pip &&\
64+
python utilities/install.py ${BUILD_ARGS} --workspace $WORKSPACE_VERSION
4965

50-
RUN jupyter labextension disable @jupyterlab/hub-extension
5166

52-
RUN chown $NB_UID .
53-
RUN chown -R $NB_UID workspace
67+
RUN mv workspace /opt/workspace/tutorials
68+
RUN chown -R $NB_UID /opt/workspace/tutorials
69+
RUN ln -s /opt/workspace workspace
5470

55-
# Temp fixes for eeg plots
56-
ENV NEURON_HOME=/opt/conda
57-
# For lfpykit 0.4
58-
# RUN wget -P $(pip show LFPykit | grep "Location:" | awk '{print $2"/lfpykit"}') https://www.parralab.org/nyhead/sa_nyhead.mat
59-
# For lpfykit 0.5
60-
ENV NP_LFPYKIT_HEAD_FILE=/home/jovyan/nyhead.mat
71+
RUN jupyter labextension disable @jupyterlab/hub-extension
6172
RUN wget --no-check-certificate -O $NP_LFPYKIT_HEAD_FILE https://www.parralab.org/nyhead/sa_nyhead.mat
6273

6374
USER $NB_UID
6475

76+
6577
EXPOSE 8888
6678

79+
ENTRYPOINT ["tini", "-g", "--"]
80+
81+
6782

83+
CMD ./NetPyNE-UI

README.md

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,59 @@ your system and you have had troubles installing it you can opt for the Virtual
3030

3131
### Python Dependencies
3232

33-
We recommend the use of a new python 3 virtual environment:
33+
We recommend the use of a new python 3.7 virtual environment.
34+
Currently, NetPyNE-UI only supports Python 3.7, but that can change in the future.
35+
36+
For NetPyNE-UI, the preferred way of creating a virtual env is to pass by conda/miniconda or mamba/micromamba.
37+
The pyenv tool can be also used, but it requires to be compiled with some special options to have NEURON running properly the simulation using `nrniv`.
38+
The reason behind this is that NEURON is distributed as a Python wheel with a specific option which force NEURON to look for the CPython dynamic lib.
39+
However, pyenv by default installs the static version of the CPython lib, resulting in `nrniv -python` not being able to run.
40+
41+
The way of creating the virtualenv using (mini)conda is the following
42+
43+
```bash
44+
conda create -n netpyne python=3.7
45+
conda activate netpyne
46+
```
47+
48+
Here is how to create the virtualenv using (micro)mamba
49+
50+
```bash
51+
mamba create -n netpyne python=3.7 -c conda-forge
52+
mamba activate netpyne
53+
```
54+
55+
You can also directly create a virtualenv using your `python3` executable, obviously if it's the 3.7 version.
3456

3557
```bash
3658
python3 -m venv npenv
3759
source npenv/bin/activate
3860
```
3961

40-
Or, with conda
62+
If you want to use anyway pyenv, here is how to properly create the virtualenv and activate it.
4163

4264
```bash
43-
conda create -n netpyne python=3.7
44-
conda activate netpyne
65+
env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install --verbose 3.7.17
66+
pyenv virtualenv 3.7.17 netpyne
67+
pyenv shell netpyne
4568
```
4669

4770
### Run install script
4871

72+
When you are in your virtualenv, here is how you can install the "basic" version of NetPyNE-UI:
73+
4974
```bash
5075
python utilities/install.py
5176
```
5277

78+
If you want to have a different version of NetPyNE or geppetto meta, you can pass the version you want to the installer:
79+
80+
```bash
81+
python utilities/install.py --dev --netpyne development --geppetto development --no-test
82+
```
83+
84+
This command will install the `development` version of netpyne and geppetto and disable the tests during the installation.
85+
5386
### Start application
5487

5588
```bash
@@ -62,6 +95,15 @@ For debugging you can use `run.py` instead
6295
python run.py
6396
```
6497

98+
To run the UI in dev mode, you need to run `python run.py` in one terminal, and use `yarn` from the `webapp` folder, using node v14 (use `nvm` if you need to have a different version of node than the one installed on your system):
99+
100+
```bash
101+
cd webapp
102+
yarn start
103+
```
104+
105+
You can then navigate to `http://127.0.0.1:8081/` to access the dev version of the UI.
106+
65107
## Run NetPyNE User Interface in Docker
66108

67109
Ensure that you have Docker installed on your system.
@@ -75,7 +117,7 @@ docker build -t netpyne-ui .
75117
Run the image
76118

77119
```bash
78-
docker run -p 8888:8888 netpyne-ui
120+
docker run -p 8888:8888 netpyne-ui
79121
```
80122

81123
## End-to-end tests

jupyter_hub/Dockerfile_spawner

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ RUN /bin/bash -c "INCUBATOR_VER=${INCUBATOR_VER} source activate snakes && pip i
1616
# Clone NetPyNE-UI and install the development version
1717
RUN wget https://github.com/MetaCell/NetPyNE-UI/archive/$netpyneuiBranch.zip -q
1818
RUN unzip $netpyneuiBranch.zip
19-
WORKDIR /home/jovyan/work/NetPyNE-UI-$netpyneuiBranch/utilities
19+
WORKDIR /opt/workspace-$netpyneuiBranch/utilities
2020
RUN /bin/bash -c "source activate snakes && python --version"
2121
RUN /bin/bash -c "source activate snakes && exec python install.py branch $netpyneuiBranch"
2222
WORKDIR /home/jovyan
2323
RUN git clone https://github.com/Neurosim-lab/netpyne_workspace
2424
WORKDIR /home/jovyan/workspace
25-
RUN ln -sfn /home/jovyan/work/NetPyNE-UI-$netpyneuiBranch/netpyne_ui/tests tests
25+
RUN ln -sfn /opt/workspace-$netpyneuiBranch/netpyne_ui/tests tests
2626

2727
# Copy jupyterhub_config
28-
# RUN cp /home/jovyan/work/NetPyNE-UI-$netpyneuiBranch/jupyterhub_config.py .
28+
# RUN cp /opt/workspace-$netpyneuiBranch/jupyterhub_config.py .
2929

3030
CMD /bin/bash -c "source activate snakes && exec jupyterhub-singleuser --debug --NotebookApp.default_url=/geppetto --NotebookApp.token='' --library=netpyne_ui"

k8s/cf_values.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ hub:
1111
shutdownOnLogout: true
1212
extraConfig:
1313
timing: |
14-
c.Spawner.notebook_dir = '/home/jovyan/work/NetPyNE-UI'
14+
c.Spawner.notebook_dir = '/opt/workspace'
1515
c.Spawner.default_url = '/geppetto'
1616
spawner: >-
17-
c.Spawner.args = ["--library=netpyne_ui"]
17+
c.Spawner.args = ["--library=netpyne_ui", "--NotebookApp.default_url=/geppetto"]
1818
singleuser:
1919
storage:
2020
type: none

k8s/minikube_values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ hub:
2020
c.Spawner.port = 8000
2121
c.Spawner.http_timeout = 300
2222
c.Spawner.start_timeout = 300
23-
c.Spawner.notebook_dir = '/home/jovyan/work/NetPyNE-UI'
23+
c.Spawner.notebook_dir = '/opt/workspace'
2424
c.Spawner.default_url = '/geppetto'
2525
c.Spawner.debug = True
2626
c.Spawner.disable_check_xsrf=True

netpyne_ui/netpyne_geppetto.py

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,40 @@
4747
os.chdir(constants.NETPYNE_WORKDIR_PATH)
4848

4949

50+
class NetpyneValidationError(Exception):
51+
...
52+
53+
54+
def deepcopy_wout_empty(d, memo=None):
55+
def is_empty(x):
56+
return x == '' or x == [] or x == () or x == set() or x == {} or x is None
57+
58+
# if is_empty(d):
59+
# return None
60+
memo = {} if memo is None else memo
61+
if id(d) in memo:
62+
return memo[id(d)]
63+
if isinstance(d, dict):
64+
cpy = {}
65+
for k, v in d.items():
66+
v_cpy = deepcopy_wout_empty(v, memo=memo)
67+
if is_empty(v_cpy):
68+
continue
69+
cpy[k] = memo.setdefault(id(v), v_cpy)
70+
return cpy
71+
elif isinstance(d, (list, set, tuple)):
72+
return d.__class__(memo.setdefault(id(v), deepcopy_wout_empty(v, memo=memo)) for v in d if not is_empty(v))
73+
elif hasattr(d, '__dict__'):
74+
cpy = d.__new__(d.__class__) # We skip the initializer, in case it needs some arguments
75+
for k, v in d.__dict__.items():
76+
v_cpy = deepcopy_wout_empty(v, memo=memo)
77+
# if is_empty(v_cpy): #
78+
# continue
79+
cpy.__dict__[k] = memo.setdefault(id(v), v_cpy)
80+
return cpy
81+
return d
82+
83+
5084
class NetPyNEGeppetto:
5185

5286
def __init__(self):
@@ -185,6 +219,11 @@ def instantiateNetPyNEModelInGeppetto(self, args):
185219
self.geppetto_model = self.model_interpreter.getGeppettoModel(netpyne_model)
186220

187221
return json.loads(GeppettoModelSerializer.serialize(self.geppetto_model))
222+
except NetpyneValidationError as e:
223+
message = ("Error while validating the NetPyNE model before instantiation.\n"
224+
"One or more components in your model have issues, see details below:")
225+
logging.exception(message)
226+
return utils.getJSONError(message, '\n'.join(e.args))
188227
except Exception as e:
189228
message = "Error while instantiating the NetPyNE model"
190229
logging.exception(message)
@@ -256,6 +295,26 @@ def simulate_single_model(self, experiment: model.Experiment = None, use_prev_in
256295
response = json.loads(GeppettoModelSerializer.serialize(self.geppetto_model))
257296
return response
258297

298+
299+
def validate_netParams(self):
300+
cpy = deepcopy_wout_empty(self.netParams)
301+
_, failed = sim.validator.validateNetParams(cpy)
302+
if failed:
303+
message = ""
304+
components_error = {}
305+
for entry in failed:
306+
components_error.setdefault(entry.component, []).append((entry.keyPath, entry.summary))
307+
for component, details in components_error.items():
308+
message = message + f"* Error validating {component}\n"
309+
for (keyPath, summary) in details:
310+
path = ' -> '.join(f"{key}" for key in keyPath)
311+
message = message + f" Error in {path}\n"
312+
for line in summary:
313+
message = message + f" {line}\n"
314+
message = message + "\n"
315+
raise NetpyneValidationError(message)
316+
317+
259318
def simulateNetPyNEModelInGeppetto(self, args):
260319
""" Starts simulation of the currently loaded NetPyNe model.
261320
@@ -270,8 +329,9 @@ def simulateNetPyNEModelInGeppetto(self, args):
270329
allTrials = args.get('allTrials', True)
271330
use_prev_inst = args.get('usePrevInst', False)
272331
sim_id = args.get('simId', 0)
273-
274332
try:
333+
self.validate_netParams()
334+
275335
experiment = experiments.get_current()
276336
if experiment:
277337
if self.experiments.any_in_state([model.ExperimentState.PENDING, model.ExperimentState.SIMULATING]):
@@ -300,6 +360,11 @@ def simulateNetPyNEModelInGeppetto(self, args):
300360

301361
else:
302362
return self.simulate_single_model(use_prev_inst=use_prev_inst)
363+
except NetpyneValidationError as e:
364+
message = (f"Error while validating the NetPyNE model before simulation {sim_id}.\n"
365+
"One or more components in your model have issues, see details below:")
366+
logging.exception(message)
367+
return utils.getJSONError(message, '\n'.join(e.args))
303368

304369
except Exception as e :
305370
message = f"Error while simulating the NetPyNE model: {e}. SimulationId {sim_id}"
@@ -740,6 +805,7 @@ def deleteModel(self, modelParams):
740805
return utils.getJSONReply()
741806

742807
def instantiateNetPyNEModel(self):
808+
self.validate_netParams()
743809
with redirect_stdout(sys.__stdout__):
744810
saveData = sim.allSimData if hasattr(sim, 'allSimData') and 'spkt' in sim.allSimData.keys() and len(
745811
sim.allSimData['spkt']) > 0 else False
@@ -774,7 +840,8 @@ def doIhaveInstOrSimData(self):
774840
return {'haveInstance': out[0], 'haveSimData': out[1]}
775841

776842
def rename(self, path, oldValue, newValue):
777-
command = 'sim.rename(self.' + path + ',"' + oldValue + '","' + newValue + '")'
843+
# command = 'sim.rename(self.' + path + ',"' + oldValue + '","' + newValue + '")'
844+
command = f'sim.rename(self.{path}, {oldValue!r}, {newValue!r})'
778845
logging.debug('renaming ' + command)
779846

780847
eval(command)
@@ -912,11 +979,15 @@ def getAvailableCellModels(self):
912979
cell_models.add(cm)
913980
return list(cell_models)
914981

915-
def getAvailableCellTypes(self):
916-
cell_types = set([])
917-
for p in self.netParams.cellParams:
918-
cell_types.add(p)
919-
return list(cell_types)
982+
def getAvailableCellModels(self):
983+
return ["", "VecStim", "NetStim", "IntFire1"]
984+
985+
def getAvailableStimulationDistribution(self):
986+
return ["normal", "uniform"]
987+
988+
def getAvailableStimulationPattern(self):
989+
# self.netParams.popParams[name]['spikePattern'] = {}
990+
return ["", "rhythmic", "evoked", "poisson", "gauss"]
920991

921992
def getAvailableSections(self):
922993
sections = {}

tests/frontend/e2e/jest-puppeteer.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = {
22
launch: {
3-
headless: true,
3+
headless: 'new',
44
defaultViewport: {
55
width: 1300,
66
height: 1024

0 commit comments

Comments
 (0)