Skip to content

Commit dee4f40

Browse files
authored
Merge pull request #826 from MetaCell/master
sync dev
2 parents 267c336 + eb3b3a3 commit dee4f40

30 files changed

+813
-6359
lines changed

.github/workflows/tests.yml

+256-256
Large diffs are not rendered by default.

Dockerfile

+27-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:14 as jsbuild
1+
FROM node:18 as jsbuild
22

33
ENV FOLDER=netpyne
44

@@ -11,6 +11,11 @@ RUN yarn install --network-timeout 1000000000
1111
COPY webapp .
1212
RUN yarn build-dev
1313

14+
### Download on a separate stage to run in parallel with buildkit
15+
FROM jupyter/base-notebook:hub-1.5.0 as downloads
16+
USER root
17+
RUN wget --no-check-certificate -O /nyhead.mat https://www.parralab.org/nyhead/sa_nyhead.mat
18+
1419
###
1520
FROM jupyter/base-notebook:hub-1.5.0
1621
ENV NB_UID=jovyan
@@ -31,22 +36,30 @@ COPY --chown=1000:1000 requirements.txt requirements.txt
3136
RUN --mount=type=cache,target=/root/.cache python -m pip install --upgrade pip &&\
3237
pip install -r requirements.txt --prefer-binary
3338

34-
COPY . .
35-
COPY --from=jsbuild --chown=1000:1000 $FOLDER/webapp/build webapp/build
3639

3740
# ToDo: fixme, for now remove the jupyter hub config json file because it overrides the default
3841
# and thus removes the frame ancestor cors settings
3942
RUN rm -f ~/.jupyter/*.json
4043
RUN chown $NB_UID .
4144
RUN chown $NB_UID /opt
4245
RUN rm -Rf workspace
43-
44-
USER $NB_UID
45-
4646
# sym link workspace pvc to $FOLDER
4747
RUN mkdir -p /opt/workspace
4848
RUN mkdir -p /opt/user
4949

50+
COPY netpyne_ui netpyne_ui
51+
COPY utilities utilities
52+
COPY setup.py .
53+
COPY tests tests
54+
COPY NetPyNE-UI .
55+
COPY README.rst .
56+
COPY requirements-test.txt .
57+
58+
59+
USER $NB_UID
60+
61+
62+
5063

5164
ENV NEURON_HOME=/opt/conda
5265

@@ -60,17 +73,22 @@ RUN jupyter serverextension enable --py --sys-prefix jupyter_geppetto
6073

6174
ARG BUILD_ARGS=""
6275
ARG WORKSPACE_VERSION=master
76+
6377
RUN --mount=type=cache,target=/root/.cache python -m pip install --upgrade pip &&\
64-
python utilities/install.py ${BUILD_ARGS} --workspace $WORKSPACE_VERSION
78+
python utilities/install.py ${BUILD_ARGS} --workspace $WORKSPACE_VERSION --npm-skip
6579

6680

6781
RUN mv workspace /opt/workspace/tutorials
68-
RUN chown -R $NB_UID /opt/workspace/tutorials
82+
RUN chown -R $NB_UID /opt/workspace
6983
RUN ln -s /opt/workspace workspace
7084

7185
RUN jupyter labextension disable @jupyterlab/hub-extension
72-
RUN wget --no-check-certificate -O $NP_LFPYKIT_HEAD_FILE https://www.parralab.org/nyhead/sa_nyhead.mat
7386

87+
COPY --from=downloads --chown=1000:1000 /nyhead.mat $NP_LFPYKIT_HEAD_FILE
88+
COPY --from=jsbuild --chown=1000:1000 $FOLDER/webapp/build webapp/build
89+
90+
RUN chown -R $NB_UID /home/jovyan/.jupyter
91+
RUN touch app.log && chown $NB_UID app.log
7492
USER $NB_UID
7593

7694

netpyne_ui/helpers/neuroml.py

+28-16
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
import sys
33
import logging
44
from netpyne.specs import simConfig
5+
from packaging import version
56

7+
import pyneuroml
68
from pyneuroml import pynml
79
from pyneuroml.lems import generate_lems_file_for_neuroml
810
from pyneuroml.pynml import read_neuroml2_file
@@ -13,57 +15,67 @@
1315
def convertLEMSSimulation(lemsFileName, compileMod=True):
1416
"""Converts a LEMS Simulation file
1517
16-
Converts a LEMS Simulation file (https://docs.neuroml.org/Userdocs/LEMSSimulation.html)
17-
pointing to a NeuroML 2 file into the equivalent in NetPyNE
18+
Converts a LEMS Simulation file
19+
(https://docs.neuroml.org/Userdocs/LEMSSimulation.html) pointing to a
20+
NeuroML 2 file into the equivalent in NetPyNE
21+
1822
Returns:
1923
simConfig, netParams for the model in NetPyNE
2024
"""
2125
current_path = os.getcwd()
2226
try:
23-
27+
2428
fullLemsFileName = os.path.abspath(lemsFileName)
25-
tmp_path = os.path.dirname(fullLemsFileName)
29+
tmp_path = os.path.dirname(fullLemsFileName)
2630
if tmp_path:
2731
os.chdir(tmp_path)
2832
logging.info(
2933
"Importing LEMSSimulation with NeuroML 2 network from: %s"
3034
% fullLemsFileName
3135
)
3236

33-
result = pynml.run_lems_with_jneuroml_netpyne(
34-
lemsFileName, only_generate_json=True, exit_on_fail=False)
35-
36-
if result == False:
37-
raise Exception("Error loading lems file")
37+
# feature to return output added in 1.0.9
38+
if version.parse(pyneuroml.__version__) >= version.parse("1.0.9"):
39+
result, output_msg = pynml.run_lems_with_jneuroml_netpyne(
40+
lemsFileName, only_generate_json=True, exit_on_fail=False,
41+
return_string=True, max_memory="1G")
42+
43+
if result is False:
44+
raise Exception(f"Error loading lems file: {output_msg}")
45+
else:
46+
result = pynml.run_lems_with_jneuroml_netpyne(
47+
lemsFileName, only_generate_json=True, exit_on_fail=False,
48+
max_memory="1G")
49+
50+
if result is False:
51+
raise Exception("Error loading lems file")
52+
3853
lems = pynml.read_lems_file(lemsFileName)
3954

4055
np_json_fname = fullLemsFileName.replace('.xml','_netpyne_data.json')
41-
56+
4257
return np_json_fname
4358
finally:
4459
os.chdir(current_path)
4560

4661

47-
48-
4962
def convertNeuroML2(nml2FileName, compileMod=True):
5063
"""Loads a NeuroML 2 file into NetPyNE
5164
Loads a NeuroML 2 file into NetPyNE by creating a new LEMS Simulation
52-
file (https://docs.neuroml.org/Userdocs/LEMSSimulation.html) and using jNeuroML
53-
to convert it.
65+
file (https://docs.neuroml.org/Userdocs/LEMSSimulation.html) and using
66+
jNeuroML to convert it.
5467
5568
Returns:
5669
simConfig, netParams for the model in NetPyNE
5770
"""
5871
current_path = os.getcwd()
5972
try:
6073
fullNmlFileName = os.path.abspath(nml2FileName)
61-
work_path = os.path.dirname(fullNmlFileName)
74+
work_path = os.path.dirname(fullNmlFileName)
6275
if not os.path.exists(work_path):
6376
os.makedirs(work_path)
6477
os.chdir(work_path)
6578
sys.path.append(work_path)
66-
6779

6880
logging.info(
6981
"Importing NeuroML 2 network from: %s"

netpyne_ui/netpyne_geppetto.py

+3
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,9 @@ def getAvailableCellTypes(self):
10011001
for p in self.netParams.cellParams:
10021002
cell_types.add(p)
10031003
return sorted(cell_types)
1004+
1005+
def getAvailableDensityTypes(self):
1006+
return ['uniform', '1DMap', '2DMap', 'distance']
10041007

10051008
def getAvailableRxDSections(self, selectedRegion = None):
10061009
sections = set([])

requirements.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ jupyter-core==4.9.1
2929
jupyter-server==1.11.2
3030
jupyterhub==1.5.0
3131
jupyterlab==3.2.4
32-
neuromllite==0.5.1
32+
neuromllite==0.5.4
3333
jupyterthemes==0.20.0
3434
kiwisolver==1.2.0
3535
lesscpy==0.14.0
36-
libNeuroML==0.4.0
36+
libNeuroML==0.5.1
3737
lfpykit==0.5.1
3838
lxml==4.5.1
3939
Mako==1.1.0
@@ -44,7 +44,7 @@ mistune==0.8.4
4444
multimethod==1.3
4545
nbconvert==5.6.1
4646
nbformat==5.0.6
47-
netpyne==1.0.4.1
47+
netpyne==1.0.6
4848
NEURON==8.2.2
4949
numpy==1.18.5
5050
oauthlib==3.0.1
@@ -65,7 +65,7 @@ pycparser==2.20
6565
pyecore==0.11.7
6666
pygeppetto==0.8.1
6767
PyLEMS==0.5.9
68-
pyNeuroML==0.7.1
68+
pyNeuroML==1.0.10
6969
sentry_sdk==1.5.2
7070
dacite==1.6.0
7171
h5py==3.7.0

setup.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
setuptools.setup(
2020
name="netpyne_ui",
21-
version="1.0.0",
21+
version="1.1.0",
2222
url="https://github.com/MetaCell/NetPyNE-UI",
2323
author="MetaCell",
2424
author_email="[email protected]",
@@ -42,9 +42,9 @@
4242
install_requires=[
4343
'jupyter-geppetto>=1.0.0',
4444
'NEURON>=8.2.2',
45-
'netpyne>=1.0.4.1',
46-
'neuromllite==0.5.1',
47-
'pyNeuroML>=0.7.1',
45+
'netpyne>=1.0.6',
46+
'neuromllite==0.5.4',
47+
'pyNeuroML>=1.0.10',
4848
'sentry_sdk>=1.5.2',
4949
'dacite>=1.6.0',
5050
'h5py>=3.7.0',

tests/frontend/e2e/package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/frontend/e2e/tests/ControlPanel.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const PASSWORD = 'testpassword'
3030

3131
//TESTS:
3232

33-
jest.setTimeout(300000);
33+
jest.setTimeout(3000000);
3434
let browser_control_panel;
3535
let control_panel_page;
3636

tests/frontend/e2e/tests/EEG_and_Dipole_Tut#1.test.js

+21-15
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const PASSWORD = 'testpassword'
3636

3737
//TESTS:
3838

39-
jest.setTimeout(300000);
39+
jest.setTimeout(3000000);
4040
let browser_EEG_Dipole;
4141
let EEG_Dipole_page;
4242

@@ -122,7 +122,7 @@ describe('EEG and Dipole Plot Test using Tutorial#1', () => {
122122

123123
await console.log('Loading Tutorial #1')
124124
await EEG_Dipole_page.click(selectors.TUTORIAL_1_SELECTOR, { timeout: TIMEOUT })
125-
await EEG_Dipole_page.waitForSelector(selectors.PYR_CELL_SELECTOR)
125+
await EEG_Dipole_page.waitForSelector(selectors.PYR_CELL_SELECTOR, { timeout: TIMEOUT * 2 })
126126
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT)
127127

128128

@@ -189,17 +189,20 @@ describe('EEG and Dipole Plot Test using Tutorial#1', () => {
189189
it('Dipole Plot', async () => {
190190

191191
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 2);
192+
await EEG_Dipole_page.waitForSelector(selectors.DIPOLE_PLOT_SELECTOR)
192193
await EEG_Dipole_page.click(selectors.DIPOLE_PLOT_SELECTOR)
193194
await EEG_Dipole_page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
194195

195196
await console.log('View Dipole Plot ...')
196197

197-
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 20);
198-
await EEG_Dipole_page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
199-
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT);
200-
await EEG_Dipole_page.click(selectors.DIPOLE_PLOT_SELECTOR)
201-
await EEG_Dipole_page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
202-
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 3);
198+
await EEG_Dipole_page.waitForSelector('#plot > div > div > img', { timeout: TIMEOUT * 10, hidden: false})
199+
200+
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 2);
201+
// await EEG_Dipole_page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
202+
// await EEG_Dipole_page.waitForTimeout(PAGE_WAIT);
203+
// await EEG_Dipole_page.click(selectors.DIPOLE_PLOT_SELECTOR)
204+
// await EEG_Dipole_page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
205+
// await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 3);
203206

204207
await console.log('... taking snapshot ...');
205208
expect(await EEG_Dipole_page.screenshot())
@@ -213,17 +216,20 @@ describe('EEG and Dipole Plot Test using Tutorial#1', () => {
213216
it('EEG Plot', async () => {
214217

215218
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 2);
219+
await EEG_Dipole_page.waitForSelector(selectors.EEG_PLOT_SELECTOR)
216220
await EEG_Dipole_page.click(selectors.EEG_PLOT_SELECTOR)
217-
await EEG_Dipole_page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
221+
await EEG_Dipole_page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT, hidden: false})
218222

219223
await console.log('View EEG Plot ...')
220224

221-
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 25);
222-
await EEG_Dipole_page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
223-
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 2);
224-
await EEG_Dipole_page.click(selectors.EEG_PLOT_SELECTOR)
225-
await EEG_Dipole_page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
226-
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 3);
225+
await EEG_Dipole_page.waitForSelector('#plot > div > div > img', { timeout: TIMEOUT * 10, hidden: false})
226+
227+
await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 7);
228+
// await EEG_Dipole_page.click(selectors.CONNECTIONS_PLOT_SELECTOR, { timeout: TIMEOUT })
229+
// await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 2);
230+
// await EEG_Dipole_page.click(selectors.EEG_PLOT_SELECTOR)
231+
// await EEG_Dipole_page.waitForSelector(selectors.CANVAS_SELECTOR, { timeout: TIMEOUT })
232+
// await EEG_Dipole_page.waitForTimeout(PAGE_WAIT * 3);
227233

228234
await console.log('... taking snapshot ...');
229235
expect(await EEG_Dipole_page.screenshot())

tests/frontend/e2e/tests/ExperimentManager_Tut#1.test.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const PASSWORD = 'testpassword'
3535

3636
//TESTS:
3737

38-
jest.setTimeout(300000);
38+
jest.setTimeout(3000000);
3939
let browser_experiment_manager;
4040
let experiment_manager_page;
4141

@@ -160,10 +160,11 @@ describe('Experiment Manager test using Tut#1', () => {
160160
await experiment_manager_page.click(selectors.CREATE_NEW_EXPERIMENT_SELECTOR)
161161

162162
await experiment_manager_page.waitForSelector(selectors.CREATE_NEW_EXPERIMENT_POPUP_SELECTOR)
163+
await experiment_manager_page.waitForSelector(selectors.CONFIRM_SELECTOR, { timeout: TIMEOUT, hidden: false })
163164
await experiment_manager_page.click(selectors.CONFIRM_SELECTOR)
164-
await experiment_manager_page.waitForSelector(selectors.EXPERIMENT_NAME_SELECTOR, { timeout: TIMEOUT , visible: true})
165+
await experiment_manager_page.waitForSelector(selectors.EXPERIMENT_NAME_SELECTOR, { timeout: TIMEOUT , hidden: false})
165166
await experiment_manager_page.waitForTimeout(PAGE_WAIT);
166-
await expect(experiment_manager_page).toFill(selectors.EXPERIMENT_NAME_SELECTOR, 'Test Experiment')
167+
await expect(experiment_manager_page).toFill(selectors.EXPERIMENT_NAME_SELECTOR, 'Test Experiment', { timeout: TIMEOUT, hidden: false })
167168
await experiment_manager_page.waitForTimeout(PAGE_WAIT);
168169
await experiment_manager_page.waitForSelector(selectors.PARAMETER_SELECTION_SELECTOR)
169170
await experiment_manager_page.click(selectors.PARAMETER_SELECTION_SELECTOR)

0 commit comments

Comments
 (0)