Skip to content

Commit 5cf958a

Browse files
author
Facu
authored
Merge branch 'development' into feature/127
2 parents e722c15 + 8482174 commit 5cf958a

11 files changed

Lines changed: 288 additions & 36 deletions

File tree

.dockerignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
org.geppetto.frontend.jupyter
2+
pygeppetto
3+
.vscode
4+
.ipynb_checkpoints
5+
netpyne_ui/geppetto
6+
*.egg-info
7+
notebook.ipynb
8+
.git
9+
netpyne
10+
Dockerfile
11+
Dockerfile_base
12+
Dockerfile_dev
13+
netpyne_workspace

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ org.geppetto.frontend.jupyter/
1111
init.py
1212
npm*
1313
.vscode
14-
app.log
14+
app.log

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ RUN unzip $netpyneuiBranch.zip
2323
WORKDIR /home/jovyan/netpyne_workspace
2424
RUN ln -sfn /home/jovyan/work/NetPyNE-UI-$netpyneuiBranch/netpyne_ui/tests tests
2525

26-
CMD /bin/bash -c "source activate snakes && exec jupyter notebook --debug --NotebookApp.default_url=/geppetto --NotebookApp.token='' --library=netpyne_ui"
26+
CMD /bin/bash -c "source activate snakes && exec jupyter notebook --debug --NotebookApp.default_url=/geppetto --NotebookApp.token='' --library=netpyne_ui --NotebookApp.disable_check_xsrf=True"

Dockerfile_dev

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1-
FROM metacell/jupyter-neuron:latest
1+
# FROM metacell/jupyter-neuron:latest
2+
FROM frodriguez4600/jupyter-neuron:latest
23
USER $NB_USER
34

45
ARG netpyneuiBranch=development
56
ENV netpyneuiBranch=${netpyneuiBranch}
67
RUN echo "$netpyneuiBranch";
78

8-
# Clone NetPyNE-UI and install the development version
9-
RUN wget https://github.com/MetaCell/NetPyNE-UI/archive/$netpyneuiBranch.zip -q
10-
RUN unzip $netpyneuiBranch.zip
11-
WORKDIR /home/jovyan/work/NetPyNE-UI-$netpyneuiBranch/utilities
12-
RUN /bin/bash -c "source activate snakes && python --version"
13-
RUN /bin/bash -c "source activate snakes && exec python install.py branch $netpyneuiBranch"
14-
WORKDIR /home/jovyan
15-
RUN git clone https://github.com/Neurosim-lab/netpyne_workspace
16-
WORKDIR /home/jovyan/netpyne_workspace
17-
RUN ln -sfn /home/jovyan/work/NetPyNE-UI-$netpyneuiBranch/netpyne_ui/tests tests
18-
CMD /bin/bash -c "source activate snakes && exec jupyter notebook --debug --NotebookApp.default_url=/geppetto --NotebookApp.token='' --library=netpyne_ui"
9+
ENV FOLDER=NetPyNE-UI
10+
WORKDIR /home/jovyan/work
11+
12+
COPY --chown=1000:1000 . NetPyNE-UI
13+
WORKDIR ${FOLDER}/utilities
14+
15+
RUN python install.py branch $netpyneuiBranch
16+
17+
WORKDIR /home/jovyan/work/NetPyNE-UI
18+
19+
RUN git clone https://github.com/Neurosim-lab/netpyne_workspace && rm -rf netpyne_workspace/.git
20+
WORKDIR /home/jovyan/work/NetPyNE-UI/netpyne_workspace
21+
22+
RUN ln -sfn /home/jovyan/work/NetPyNE-UI/netpyne_ui/tests ../tests
23+
CMD /bin/bash -c "cd .. && NetPyNE-UI"

NetPyNE-UI

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#!/bin/sh
2-
exec jupyter notebook --NotebookApp.default_url=/geppetto --NotebookApp.token='' --library=netpyne_ui
2+
exec jupyter notebook --NotebookApp.default_url=/geppetto --NotebookApp.token='' --library=netpyne_ui --NotebookApp.disable_check_xsrf=True

netpyne_ui/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import logging
2+
from jupyter_geppetto.webapi import RouteManager
3+
4+
from netpyne_ui import api
5+
6+
RouteManager.add_controller(api.NetPyNEController)
7+
logging.info("Adding NWBModelInterpreter")

netpyne_ui/api.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import os
2+
import logging
3+
import uuid
4+
import gzip
5+
import tarfile
6+
import shutil
7+
from zipfile import ZipFile
8+
from tempfile import TemporaryDirectory
9+
from jupyter_geppetto.webapi import get, post
10+
from notebook.base.handlers import IPythonHandler
11+
from netpyne_ui.constants import NETPYNE_WORKDIR, UPLOAD_FOLDER_NAME, ALLOWED_EXTENSIONS, UPLOAD_FOLDER_PATH
12+
13+
def allowed_file(filename, allowed_extensions=ALLOWED_EXTENSIONS):
14+
return '.' in filename and \
15+
filename.rsplit('.', 1)[1].lower() in allowed_extensions
16+
17+
18+
def send_files(handler, file_path, filename):
19+
with open(file_path, "rb") as f:
20+
handler.set_header('Content-Type', 'application/force-download')
21+
handler.set_header('Content-Disposition', f"attachment; filename={filename}")
22+
23+
try:
24+
while True:
25+
_buffer = f.read(4096)
26+
if _buffer:
27+
handler.write(_buffer)
28+
else:
29+
return
30+
except:
31+
handler.set_status(500, f"Error sending files")
32+
33+
34+
def get_file_paths(handler):
35+
file_paths = False
36+
if 'uri' in handler.request.arguments:
37+
file_paths = []
38+
tmp_file_paths = [path.decode('utf-8') for path in handler.request.arguments['uri']]
39+
for path in tmp_file_paths:
40+
if os.path.exists(path):
41+
file_paths.append(path)
42+
43+
return file_paths
44+
45+
class NetPyNEController: # pytest: no cover
46+
47+
@post('/uploads')
48+
def uploads(handler: IPythonHandler):
49+
files = handler.request.files
50+
files_saved = 0
51+
52+
if len(files) == 0 or 'file' not in files:
53+
handler.set_status(400, f"Can't find 'file' or filename is empty. Files received {len(files)}")
54+
else:
55+
56+
for f in files['file']:
57+
if not allowed_file(f.filename):
58+
logging.warn(f"Can't store file {f.filename}. Extension not allowed")
59+
continue
60+
61+
## Save to file
62+
filename = f.filename
63+
file_path = os.path.join(UPLOAD_FOLDER_PATH, filename)
64+
65+
with open(file_path, 'wb') as zf:
66+
zf.write(f['body'])
67+
68+
files_saved += 1
69+
70+
if filename.endswith('.zip'):
71+
with ZipFile(file_path) as zipObj:
72+
zipObj.extractall(UPLOAD_FOLDER_PATH)
73+
74+
elif filename.endswith('.tar.gz'):
75+
with tarfile.open(file_path, mode='r:gz') as tar:
76+
tar.extractall(UPLOAD_FOLDER_PATH)
77+
78+
elif filename.endswith('.gz'):
79+
with gzip.open(file_path, "rb") as gz, open(file_path.replace('.gz', ''), 'wb') as ff:
80+
shutil.copyfileobj(gz, ff)
81+
82+
handler.set_status(200, f"Number of files saved: {files_saved}. Number of files sent: {len(files['file'])}")
83+
84+
handler.finish()
85+
86+
@get('/downloads')
87+
def downloads(handler: IPythonHandler):
88+
89+
file_paths = get_file_paths(handler)
90+
91+
if file_paths:
92+
93+
if len(file_paths) == 0:
94+
handler.set_status(400, f"Files not found.")
95+
handler.finish()
96+
return
97+
98+
if len(file_paths) == 1:
99+
send_files(handler, file_paths[0], file_paths[0].split('/')[-1])
100+
101+
else :
102+
with TemporaryDirectory() as dir_path:
103+
tar_gz_file_name = f'{str(uuid.uuid4())}.tar.gz'
104+
tar_gz_file_path = os.path.join(dir_path, tar_gz_file_name)
105+
with tarfile.open(tar_gz_file_path, mode='w:gz') as tar:
106+
for file_path in file_paths:
107+
tar.add(file_path, os.path.join('download', file_path.split('/')[-1]))
108+
109+
send_files(handler, tar_gz_file_path, tar_gz_file_name)
110+
111+
handler.finish()

netpyne_ui/constants.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import os
2+
3+
UPLOAD_FOLDER_NAME = 'uploads'
4+
NETPYNE_WORKDIR = 'netpyne_workspace'
5+
6+
ALLOWED_EXTENSIONS = ["py", "zip", "gz", ".tar.gz", "pdf", "txt", "xls", "png", "jpeg"]
7+
8+
UPLOAD_FOLDER_PATH = os.path.join(os.getcwd(), NETPYNE_WORKDIR, UPLOAD_FOLDER_NAME)
9+
NETPYNE_WORKDIR_PATH = os.path.join(os.getcwd(), NETPYNE_WORKDIR)
10+
11+
if not os.path.exists(UPLOAD_FOLDER_PATH):
12+
os.makedirs(UPLOAD_FOLDER_PATH)
13+
14+
if not os.path.exists(NETPYNE_WORKDIR_PATH):
15+
os.makedirs(NETPYNE_WORKDIR_PATH)

netpyne_ui/netpyne_geppetto.py

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030
from jupyter_geppetto import jupyter_geppetto, synchronization, utils
3131
import imp
3232
from contextlib import redirect_stdout, redirect_stderr
33+
from netpyne_ui.constants import NETPYNE_WORKDIR_PATH
3334

34-
35+
os.chdir(NETPYNE_WORKDIR_PATH)
3536
class NetPyNEGeppetto():
3637

3738
def __init__(self):
@@ -263,6 +264,11 @@ def exportModel(self, args):
263264
sim.cfg.saveJson = True
264265
sim.saveData(include)
265266
sim.cfg.saveJson = False
267+
268+
with open(f"{sim.cfg.filename}.json") as json_file:
269+
data = json.load(json_file)
270+
return data
271+
266272
return utils.getJSONReply()
267273
except:
268274
return utils.getJSONError("Error while exporting the NetPyNE model", sys.exc_info())
@@ -287,18 +293,25 @@ def importNeuroML(self, modelParams):
287293
return utils.getJSONError("Error while exporting the NetPyNE model", sys.exc_info())
288294

289295
def deleteModel(self, modelParams):
296+
290297
try:
291298
with redirect_stdout(sys.__stdout__):
292299
self.netParams = specs.NetParams()
293300
self.simConfig = specs.SimConfig()
294-
self.netParams.todict()
295-
self.netParams.todict()
296-
if self.doIhaveInstOrSimData()['haveInstance']: sim.clearAll()
301+
sim.initialize(specs.NetParams(), specs.SimConfig())
297302
self.geppetto_model = None
298-
return utils.getJSONReply()
299-
300303
except:
301304
return utils.getJSONError("Error while exporting the NetPyNE model", sys.exc_info())
305+
306+
try:
307+
# This function fails is some keys don't exists
308+
# sim.clearAll()
309+
self.clearSim()
310+
311+
except:
312+
pass
313+
314+
return utils.getJSONReply()
302315

303316
def instantiateNetPyNEModel(self):
304317
with redirect_stdout(sys.__stdout__):
@@ -360,16 +373,17 @@ def getPlotSettings(self, plot):
360373
def getDirList(self, dir=None, onlyDirs = False, filterFiles=False):
361374
# Get Current dir
362375
if dir == None or dir == '':
363-
dir = os.getcwd()
376+
dir = os.path.join(os.getcwd(), NETPYNE_WORKDIR_PATH)
364377
dir_list = []
378+
file_list = []
365379
for f in sorted(os.listdir(str(dir)), key=str.lower):
366380
ff=os.path.join(dir,f)
367381
if os.path.isdir(ff):
368-
dir_list.insert(0, {'title': f, 'path': ff, 'load': False, 'children': [{'title': 'Loading...'}]})
382+
dir_list.append({'title': f, 'path': ff, 'load': False, 'children': [{'title': 'Loading...'}]})
369383
elif not onlyDirs:
370384
if not filterFiles or os.path.isfile(ff) and ff.endswith(filterFiles):
371-
dir_list.append({'title': f, 'path': ff})
372-
return dir_list
385+
file_list.append({'title': f, 'path': ff})
386+
return dir_list + file_list
373387

374388
def getPlot(self, plotName, LFPflavour):
375389
try:
@@ -545,7 +559,8 @@ def header(title, spacer='-'):
545559

546560
script.write(header('end script', spacer='='))
547561

548-
return utils.getJSONReply()
562+
with open(fname) as f:
563+
return f.read()
549564

550565
except:
551566
return utils.getJSONError("Error while importing the NetPyNE model", sys.exc_info())
@@ -652,6 +667,52 @@ def propagate_syn_mech_rename(self, new, old):
652667
self.netParams.stimTargetParams[label]['synMech'] = new
653668

654669

670+
def clearSim(self):
671+
# clean up
672+
sim.pc.barrier()
673+
sim.pc.gid_clear() # clear previous gid settings
674+
675+
# clean cells and simData in all nodes
676+
sim.clearObj([cell.__dict__ if hasattr(cell, '__dict__') else cell for cell in sim.net.cells])
677+
if 'stims' in list(sim.simData.keys()):
678+
sim.clearObj([stim for stim in sim.simData['stims']])
679+
680+
for key in list(sim.simData.keys()): del sim.simData[key]
681+
682+
if hasattr(sim, 'net'):
683+
for c in sim.net.cells: del c
684+
for p in sim.net.pops: del p
685+
if hasattr(sim.net, 'params'):
686+
del sim.net.params
687+
688+
689+
# clean cells and simData gathered in master node
690+
if sim.rank == 0:
691+
if hasattr(sim.net, 'allCells'):
692+
sim.clearObj([cell.__dict__ if hasattr(cell, '__dict__') else cell for cell in sim.net.allCells])
693+
if hasattr(sim, 'allSimData'):
694+
if 'stims' in list(sim.allSimData.keys()):
695+
sim.clearObj([stim for stim in sim.allSimData['stims']])
696+
for key in list(sim.allSimData.keys()): del sim.allSimData[key]
697+
del sim.allSimData
698+
699+
700+
import matplotlib
701+
matplotlib.pyplot.clf()
702+
matplotlib.pyplot.close('all')
703+
704+
if hasattr(sim, 'net'):
705+
if hasattr(sim.net, 'allCells'):
706+
for c in sim.net.allCells: del c
707+
del sim.net.allCells
708+
if hasattr(sim.net, 'allPops'):
709+
for p in sim.net.allPops: del p
710+
711+
del sim.net
712+
713+
import gc; gc.collect()
714+
715+
655716
logging.info("Initialising NetPyNE UI")
656717
netpyne_geppetto = NetPyNEGeppetto()
657718
logging.info("NetPyNE UI initialised")

run.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
sys.argv.append('--NotebookApp.default_url=/geppetto')
1414
sys.argv.append("--NotebookApp.token=''")
1515
sys.argv.append('--library=netpyne_ui')
16+
sys.argv.append('--NotebookApp.disable_check_xsrf=True')
1617

1718
app = NotebookApp.instance()
1819
app.initialize(sys.argv)

0 commit comments

Comments
 (0)