Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
e025db0
Configurable notebook name
filippomc Mar 19, 2021
7702ff8
Create notebook inside workspace
filippomc Mar 22, 2021
3554b83
Reduce eslint errors
May 18, 2021
7e6f9ca
Reduce eslint errors
May 19, 2021
aff6617
Reduce eslint errors
May 19, 2021
505afd6
Reduce eslint errors
May 19, 2021
a512ed9
#263 Remove obsolete clearSim method
May 19, 2021
27f0928
Merge pull request #297 from MetaCell/feature/eslint_errors
filippomc May 26, 2021
f201ef7
Merge pull request #298 from MetaCell/feature/263_sim_clearAll
filippomc May 26, 2021
4e5a299
Merge pull request #329 from MetaCell/release/0.7.0
Jun 17, 2021
e6c3980
Merge branch 'master' of github.com:MetaCell/NetPyNE-UI into osb2
filippomc Jun 18, 2021
2dad8e4
workspace installaztion made optional
filippomc Jun 18, 2021
de432fb
Delete workspace folder
filippomc Jun 18, 2021
a8d0e9c
Small import fix
filippomc Jun 18, 2021
98d7e81
#328 Remove workspace folder & improve install.py
lrebscher Jun 21, 2021
10e6675
Use notebook tornado 6.1 with notebook 6.4.0
lrebscher Jun 21, 2021
07f2ebc
Merge pull request #339 from MetaCell/feature/328_fix_install_script
filippomc Jun 21, 2021
152b062
#326 Allow json extension in upload
Jun 23, 2021
5a39bf4
Merge pull request #343 from MetaCell/feature/326_allow_json_upload
Jun 23, 2021
340d361
Bump up NEURON version to 8.0.0
Jul 2, 2021
06b9edc
Allow netpyne only to be installed from source
filippomc Jul 2, 2021
1670a27
Allow netpyne only to be installed from source
filippomc Jul 2, 2021
0356d1d
Merge pull request #353 from MetaCell/feature/neuron_8.0.0
filippomc Jul 2, 2021
f6d014c
remove phantom.js
Muhaddatha Jul 7, 2021
6dddc03
Merge pull request #361 from MetaCell/phantom
Jul 8, 2021
905ad13
#191 add versions
Muhaddatha Jul 20, 2021
d23dff5
#201 use suggested file name when exporting Python
Muhaddatha Jul 20, 2021
fca916d
#201 Use Base64 encoding to transfer file content
Jul 21, 2021
982d950
Merge pull request #365 from MetaCell/feature/201_fix_filename_export
Jul 21, 2021
c73fe40
#357 install js-base64
Muhaddatha Jul 26, 2021
2268f30
#357 prevent netwoork creation or simulation
Muhaddatha Jul 26, 2021
db57b0b
#369 Fix bug in getPlot
Jul 27, 2021
e96d184
#357 remove node_modules files
Muhaddatha Jul 27, 2021
9afabe6
#357 check for null variable
Muhaddatha Jul 27, 2021
34aa6e6
Merge branch 'feature/357_stop_network_creation' of https://github.co…
Muhaddatha Jul 27, 2021
cbd774d
#357 Disable automaticInstantiation by default
Jul 28, 2021
fccbef7
Merge pull request #367 from MetaCell/feature/357_stop_network_creation
Jul 28, 2021
b14fca7
#191 use primary color for app versions
Muhaddatha Jul 28, 2021
0230675
#374 remove explore view options
Muhaddatha Jul 28, 2021
b5f1a74
#347 add create and simulate option in model menu
Muhaddatha Jul 28, 2021
bd0e2d7
#347 create split button component
Muhaddatha Jul 29, 2021
dd531dc
#347 use split button in top bar component
Muhaddatha Jul 29, 2021
28e8975
#191 add links to about box
Muhaddatha Jul 29, 2021
8318a6d
#347 linting fix + add 'back to edit' button
Muhaddatha Aug 2, 2021
14ab223
#347 small fixes, style simulate button
Muhaddatha Aug 2, 2021
ae6bf80
#347 remove borders on simulate button
Muhaddatha Aug 2, 2021
28207e2
#347 update netpyne version info
Muhaddatha Aug 2, 2021
ba85c4c
Merge pull request #363 from MetaCell/Feature/191_add_app_version
Aug 3, 2021
fbdfa32
#347 implement requested changes, remove extra margin
Muhaddatha Aug 3, 2021
b3096de
fixed importModel to transform dict to specs object. Added test cases.
enicolasgomez Aug 3, 2021
e8b9a82
Added test example to models folder
enicolasgomez Aug 4, 2021
d60d484
#347 remove unused import and variables
Muhaddatha Aug 4, 2021
4f33857
#347 display rocket in edit view
Muhaddatha Aug 4, 2021
87149de
Merge pull request #376 from MetaCell/feature/347_change_topbar_buttons
Aug 5, 2021
80b6dc5
#347 Always instantiate network
Aug 5, 2021
9d8002a
Improved path location handling
enicolasgomez Aug 5, 2021
53fd7d8
Merge pull request #379 from MetaCell/issue/375-dev
Aug 5, 2021
0d52ffd
Merge pull request #392 from MetaCell/feature/347_fix_instantiate_logic
Aug 10, 2021
2835862
Merge branch 'development' of github.com:MetaCell/NetPyNE-UI into osb2
filippomc Aug 11, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ utilities/x86_64
.idea
*.iml
x86_64
.jupyter-config
.jupyter-config
venv
3 changes: 2 additions & 1 deletion netpyne_ui/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging

from jupyter_geppetto.webapi import RouteManager

from netpyne_ui import api

RouteManager.add_controller(api.NetPyNEController)
RouteManager.add_controller(api.NetPyNEController)
83 changes: 62 additions & 21 deletions netpyne_ui/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from tempfile import TemporaryDirectory
from jupyter_geppetto.webapi import get, post
from notebook.base.handlers import IPythonHandler
from netpyne_ui.constants import NETPYNE_WORKDIR, UPLOAD_FOLDER_NAME, ALLOWED_EXTENSIONS, UPLOAD_FOLDER_PATH
from netpyne_ui.constants import ALLOWED_EXTENSIONS, UPLOAD_FOLDER_PATH

def allowed_file(filename, allowed_extensions=ALLOWED_EXTENSIONS):
return '.' in filename and \
Expand All @@ -18,15 +18,16 @@ def allowed_file(filename, allowed_extensions=ALLOWED_EXTENSIONS):
def send_files(handler, file_path, filename):
with open(file_path, "rb") as f:
handler.set_header('Content-Type', 'application/force-download')
handler.set_header('Content-Disposition', f"attachment; filename={filename}")
handler.set_header('Content-Disposition',
f"attachment; filename={filename}")

try:
while True:
_buffer = f.read(4096)
if _buffer:
handler.write(_buffer)
else:
return
return
except:
handler.set_status(500, f"Error sending files")

Expand All @@ -35,36 +36,40 @@ def get_file_paths(handler):
file_paths = False
if 'uri' in handler.request.arguments:
file_paths = []
tmp_file_paths = [path.decode('utf-8') for path in handler.request.arguments['uri']]
tmp_file_paths = [path.decode('utf-8')
for path in handler.request.arguments['uri']]
for path in tmp_file_paths:
if os.path.exists(path):
file_paths.append(path)

return file_paths


class NetPyNEController: # pytest: no cover

@post('/uploads')
def uploads(handler: IPythonHandler):
files = handler.request.files
files_saved = 0

if len(files) == 0 or 'file' not in files:
handler.set_status(400, f"Can't find 'file' or filename is empty. Files received {len(files)}")
handler.set_status(
400, f"Can't find 'file' or filename is empty. Files received {len(files)}")
else:

for f in files['file']:
if not allowed_file(f.filename):
logging.warn(f"Can't store file {f.filename}. Extension not allowed")
logging.warn(
f"Can't store file {f.filename}. Extension not allowed")
continue

## Save to file
# Save to file
filename = f.filename
file_path = os.path.join(UPLOAD_FOLDER_PATH, filename)

with open(file_path, 'wb') as zf:
zf.write(f['body'])

files_saved += 1

if filename.endswith('.zip'):
Expand All @@ -78,34 +83,70 @@ def uploads(handler: IPythonHandler):
elif filename.endswith('.gz'):
with gzip.open(file_path, "rb") as gz, open(file_path.replace('.gz', ''), 'wb') as ff:
shutil.copyfileobj(gz, ff)

handler.set_status(200, f"Number of files saved: {files_saved}. Number of files sent: {len(files['file'])}")

handler.set_status(
200, f"Number of files saved: {files_saved}. Number of files sent: {len(files['file'])}")

handler.finish()

@get('/downloads')
def downloads(handler: IPythonHandler):

file_paths = get_file_paths(handler)

if file_paths:

if len(file_paths) == 0:
handler.set_status(400, f"Files not found.")
handler.finish()
return

if len(file_paths) == 1:
send_files(handler, file_paths[0], file_paths[0].split('/')[-1])

else :
send_files(handler, file_paths[0],
file_paths[0].split('/')[-1])

else:
with TemporaryDirectory() as dir_path:
tar_gz_file_name = f'{str(uuid.uuid4())}.tar.gz'
tar_gz_file_path = os.path.join(dir_path, tar_gz_file_name)
with tarfile.open(tar_gz_file_path, mode='w:gz') as tar:
for file_path in file_paths:
tar.add(file_path, os.path.join('download', file_path.split('/')[-1]))
tar.add(file_path, os.path.join(
'download', file_path.split('/')[-1]))

send_files(handler, tar_gz_file_path, tar_gz_file_name)

handler.finish()


def create_notebook(filename):
import nbformat as nbf
from nbformat.v4.nbbase import new_notebook
from nbformat import sign
import codecs

directory = os.path.dirname(filename)
if not os.path.exists(directory):
os.makedirs(directory)
nb0 = new_notebook(cells=[nbf.v4.new_markdown_cell("""# Welcome to the NetPyNE-ui!

"""),
nbf.v4.new_code_cell(
'netpyne_geppetto.netParams'),
nbf.v4.new_code_cell(
'netpyne_geppetto.simConfig')
], metadata={"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
}})

f = codecs.open(filename, encoding='utf-8', mode='w')

nbf.write(nb0, filename)
f.close()


# TODO move to jupyter geppetto, using notebook dir path
if os.path.exists('workspace') and not os.path.exists('workspace/notebook.ipynb'):
create_notebook('workspace/notebook.ipynb')
2 changes: 1 addition & 1 deletion netpyne_ui/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
UPLOAD_FOLDER_NAME = 'uploads'
NETPYNE_WORKDIR = 'workspace'

ALLOWED_EXTENSIONS = ["py", "zip", "gz", ".tar.gz", "pdf", "txt", "xls", "png", "jpeg", "hoc"]
ALLOWED_EXTENSIONS = ["py", "zip", "gz", ".tar.gz", "pdf", "txt", "xls", "png", "jpeg", "hoc", "json"]
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(HERE)
UPLOAD_FOLDER_PATH = os.path.join(ROOT, NETPYNE_WORKDIR, UPLOAD_FOLDER_NAME)
Expand Down
112 changes: 40 additions & 72 deletions netpyne_ui/netpyne_geppetto.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
import subprocess
import logging
import re
import base64

from netpyne import specs, sim, analysis
from netpyne.specs.utils import validateFunction
from netpyne.conversion.neuronPyHoc import mechVarList
from netpyne.metadata import metadata
from netpyne_ui.netpyne_model_interpreter import NetPyNEModelInterpreter
from pygeppetto.model.model_serializer import GeppettoModelSerializer
import matplotlib.pyplot as plt
from pygeppetto import ui
import numpy as np
import neuron
Expand Down Expand Up @@ -231,6 +231,12 @@ def importModel(self, modelParameters):
# Import Model attributes
self.netParams = getattr(net_params_module_name, str(modelParameters["netParamsVariable"]))

if isinstance(self.netParams, dict):
self.netParams = specs.NetParams(self.netParams)

if isinstance(self.simConfig, dict):
self.simConfig = specs.SimConfig(self.simConfig)

for key, value in self.netParams.cellParams.items():
if hasattr(value, 'todict'):
self.netParams.cellParams[key] = value.todict()
Expand Down Expand Up @@ -329,12 +335,9 @@ def deleteModel(self, modelParams):
return utils.getJSONError("Error while exporting the NetPyNE model", sys.exc_info())

try:
# This function fails is some keys don't exists
# sim.clearAll()
# TODO: as part of #264 we should remove the method and use clearAll intstead
self.clearSim()
sim.clearAll()
except:
pass
logging.exception("Failed to clear simulation")

return utils.getJSONReply()

Expand Down Expand Up @@ -432,7 +435,7 @@ def getPlot(self, plotName, LFPflavour, theme='gui'):
# This arg brings dark theme. But some plots are broken by it
args['theme'] = theme

if plotName in ("iplotConn", "iplot2Dnet") and sim.net.allCells:
if plotName in ("iplotConn", "iplot2Dnet") and hasattr(sim, 'net') and sim.net.allCells:
# To prevent unresponsive kernel, we don't show conns if they become too many
num_conn = sum([len(cell.conns) for cell in sim.net.allCells if cell.conns])
if num_conn > NUM_CONN_LIMIT:
Expand Down Expand Up @@ -597,42 +600,51 @@ def header(title, spacer='-'):
params = ['popParams', 'cellParams', 'synMechParams']
params += ['connParams', 'stimSourceParams', 'stimTargetParams']

fname = args['fileName'] if args['fileName'][-3:] == '.py' else args['fileName'] + '.py'
fname = args['fileName']
if not fname:
# default option
fname = 'output.py'

if not fname[-3:] == '.py':
fname = f"{fname}.py"

# TODO: use methods offered by netpyne to create this script!
with open(fname, 'w') as script:
script.write('from netpyne import specs, sim\n')
script.write(header('documentation'))
script.write("''' Script generated with NetPyNE-UI. Please visit:\n")
script.write(" - https://www.netpyne.org\n - https://github.com/MetaCell/NetPyNE-UI\n'''\n")
script.write(header('script', spacer='='))
script.write('netParams = specs.NetParams()\n')
script.write('simConfig = specs.SimConfig()\n')
script.write(header('single value attributes'))
script.write("from netpyne import specs, sim\n")
script.write(header("documentation"))
script.write("Script generated with NetPyNE-UI. Please visit:\n")
script.write(" - https://www.netpyne.org\n - https://github.com/MetaCell/NetPyNE-UI\n\n")
script.write(header("script", spacer="="))
script.write("netParams = specs.NetParams()\n")
script.write("simConfig = specs.SimConfig()\n")
script.write(header("single value attributes"))
for attr, value in list(self.netParams.__dict__.items()):
if attr not in params:
if value != getattr(specs.NetParams(), attr):
script.write('netParams.' + attr + ' = ')
script.write(convert2bool(json.dumps(value, indent=4)) + '\n')
script.write("netParams." + attr + " = ")
script.write(convert2bool(json.dumps(value, indent=4)) + "\n")

script.write(header('network attributes'))
script.write(header("network attributes"))
for param in params:
for key, value in list(getattr(self.netParams, param).items()):
script.write("netParams." + param + "['" + key + "'] = ")
script.write(convert2bool(json.dumps(value, indent=4)) + '\n')
script.write("netParams." + param + "[" + key + "] = ")
script.write(convert2bool(json.dumps(value, indent=4)) + "\n")

script.write(header('network configuration'))
script.write(header("network configuration"))
for attr, value in list(self.simConfig.__dict__.items()):
if value != getattr(specs.SimConfig(), attr):
script.write('simConfig.' + attr + ' = ')
script.write(convert2bool(json.dumps(value, indent=4)) + '\n')
script.write("simConfig." + attr + " = ")
script.write(convert2bool(json.dumps(value, indent=4)) + "\n")

script.write(header('create simulate analyze network'))
script.write('# sim.createSimulateAnalyze(netParams=netParams, simConfig=simConfig)\n')
script.write(header("create simulate analyze network"))
script.write("# sim.createSimulateAnalyze(netParams=netParams, simConfig=simConfig)\n")

script.write(header('end script', spacer='='))
script.write(header("end script", spacer="="))

with open(fname) as f:
return f.read()
file_b64 = base64.b64encode(bytes(f.read(), 'utf-8')).decode()
export_info = {"fileContent": file_b64, "fileName": fname}
return export_info

except:
return utils.getJSONError("Error while importing the NetPyNE model", sys.exc_info())
Expand Down Expand Up @@ -740,50 +752,6 @@ def propagate_syn_mech_rename(self, new, old):
else:
self.netParams.stimTargetParams[label]['synMech'] = new

def clearSim(self):
# clean up
sim.pc.barrier()
sim.pc.gid_clear() # clear previous gid settings

# clean cells and simData in all nodes
sim.clearObj([cell.__dict__ if hasattr(cell, '__dict__') else cell for cell in sim.net.cells])
if 'stims' in list(sim.simData.keys()):
sim.clearObj([stim for stim in sim.simData['stims']])

for key in list(sim.simData.keys()): del sim.simData[key]

if hasattr(sim, 'net'):
for c in sim.net.cells: del c
for p in sim.net.pops: del p
if hasattr(sim.net, 'params'):
del sim.net.params

# clean cells and simData gathered in master node
if sim.rank == 0:
if hasattr(sim.net, 'allCells'):
sim.clearObj([cell.__dict__ if hasattr(cell, '__dict__') else cell for cell in sim.net.allCells])
if hasattr(sim, 'allSimData'):
if 'stims' in list(sim.allSimData.keys()):
sim.clearObj([stim for stim in sim.allSimData['stims']])
for key in list(sim.allSimData.keys()): del sim.allSimData[key]
del sim.allSimData

import matplotlib
matplotlib.pyplot.clf()
matplotlib.pyplot.close('all')

if hasattr(sim, 'net'):
if hasattr(sim.net, 'allCells'):
for c in sim.net.allCells: del c
del sim.net.allCells
if hasattr(sim.net, 'allPops'):
for p in sim.net.allPops: del p

del sim.net

import gc;
gc.collect()

def create_celltype_from_template(self, label="CellType", conds={}, cell_template_name="Blank"):
try:
with redirect_stdout(sys.__stdout__):
Expand Down
21 changes: 21 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading