Skip to content

Commit 06ea773

Browse files
authored
Merge pull request #34 from irahulsonkar/NeuroML_JupyterNotebook
ET notebook updated
2 parents 8a3ddd4 + 9d23ca8 commit 06ea773

3 files changed

Lines changed: 141 additions & 56 deletions

File tree

notebooks/NeuroML_Generic_ET/NeuroML_Notebook.ipynb

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"tags": []
1616
},
1717
"source": [
18-
"## *Source path and filename*"
18+
"## *Source path and LEMS filename*"
1919
]
2020
},
2121
{
@@ -27,7 +27,7 @@
2727
{
2828
"data": {
2929
"application/vnd.jupyter.widget-view+json": {
30-
"model_id": "85e1f62a3c8c4b17a29bf5053e25406e",
30+
"model_id": "c16e3aa514f84de687804ec6107782e3",
3131
"version_major": 2,
3232
"version_minor": 0
3333
},
@@ -41,7 +41,7 @@
4141
{
4242
"data": {
4343
"application/vnd.jupyter.widget-view+json": {
44-
"model_id": "a986529d085d4979a7f88e8a17a11b78",
44+
"model_id": "09600b89ebcc4e0695f83137defddfde",
4545
"version_major": 2,
4646
"version_minor": 0
4747
},
@@ -57,7 +57,7 @@
5757
"import ipywidgets\n",
5858
"import ui_widget\n",
5959
"from importlib.machinery import SourceFileLoader\n",
60-
"%matplotlib ipympl\n",
60+
"%matplotlib widget\n",
6161
"\n",
6262
"#widget to read input files\n",
6363
"display(ui_widget.header,ui_widget.loader)"
@@ -70,19 +70,30 @@
7070
"tags": []
7171
},
7272
"source": [
73-
"## *Parse NML files and build basic dashboard*"
73+
"## *Parse NML files and build dashboard*"
7474
]
7575
},
7676
{
7777
"cell_type": "code",
78-
"execution_count": 2,
78+
"execution_count": 3,
7979
"id": "5f912104-c914-4f01-a3f4-2c9f01707b55",
80-
"metadata": {},
80+
"metadata": {
81+
"scrolled": false
82+
},
8183
"outputs": [
84+
{
85+
"name": "stdout",
86+
"output_type": "stream",
87+
"text": [
88+
"Skipping file : Cells.xml <- not in source directory\n",
89+
"Skipping file : Networks.xml <- not in source directory\n",
90+
"Skipping file : Simulation.xml <- not in source directory\n"
91+
]
92+
},
8293
{
8394
"data": {
8495
"application/vnd.jupyter.widget-view+json": {
85-
"model_id": "a497418a71e44e34ab3875af6fc8ecb0",
96+
"model_id": "16839e9e06924d13a8c659c7271db7e5",
8697
"version_major": 2,
8798
"version_minor": 0
8899
},
@@ -96,12 +107,26 @@
96107
{
97108
"data": {
98109
"application/vnd.jupyter.widget-view+json": {
99-
"model_id": "edfde4b9115b42a490a19e5862f23842",
110+
"model_id": "3df6439f5aee4ba1b1df8da601429f21",
111+
"version_major": 2,
112+
"version_minor": 0
113+
},
114+
"text/plain": [
115+
"HBox(children=(Button(button_style='info', description='Update Model', style=ButtonStyle(), tooltip='Update Ne…"
116+
]
117+
},
118+
"metadata": {},
119+
"output_type": "display_data"
120+
},
121+
{
122+
"data": {
123+
"application/vnd.jupyter.widget-view+json": {
124+
"model_id": "cf3d8e6602fa407c98499114c9e8b3bd",
100125
"version_major": 2,
101126
"version_minor": 0
102127
},
103128
"text/plain": [
104-
"HBox(children=(Button(button_style='warning', description='Validate Model', style=ButtonStyle(), tooltip='Vali…"
129+
"Output()"
105130
]
106131
},
107132
"metadata": {},
@@ -110,7 +135,7 @@
110135
{
111136
"data": {
112137
"application/vnd.jupyter.widget-view+json": {
113-
"model_id": "dc4beb078c8949c4961358711f705601",
138+
"model_id": "b40e20ed899e4fb295c9fc06e4b3be57",
114139
"version_major": 2,
115140
"version_minor": 0
116141
},
@@ -124,7 +149,7 @@
124149
{
125150
"data": {
126151
"application/vnd.jupyter.widget-view+json": {
127-
"model_id": "20d5200f22384baeac95d32ea42ecd8c",
152+
"model_id": "d28dff9ca6e44fddb74d8006a3713219",
128153
"version_major": 2,
129154
"version_minor": 0
130155
},
@@ -138,7 +163,7 @@
138163
{
139164
"data": {
140165
"application/vnd.jupyter.widget-view+json": {
141-
"model_id": "58f81e89b32a4988af3280bc315b4054",
166+
"model_id": "d7576cdda6a24b3c9b5fe5d0dd79277d",
142167
"version_major": 2,
143168
"version_minor": 0
144169
},
@@ -159,15 +184,15 @@
159184
"nmlPython = SourceFileLoader(\"nml2jupyter_ver2.py\",\"nml2jupyter_ver2.py\").load_module()\n",
160185
"runner = nmlPython.nml2jupyter(path2source, fname_LEMS)\n",
161186
"\n",
162-
"trees = runner.parseNML()\n",
163-
"runner.generateDashboard(trees)\n",
187+
"runner.parseNML()\n",
188+
"runner.generateDashboard()\n",
164189
"runner.loadGUI()"
165190
]
166191
},
167192
{
168193
"cell_type": "code",
169194
"execution_count": null,
170-
"id": "5fcd69c9-d5b9-4095-b489-bc0b5e142a08",
195+
"id": "ef9e271b-45b6-4864-be3d-e55628cb1735",
171196
"metadata": {},
172197
"outputs": [],
173198
"source": []
@@ -189,7 +214,7 @@
189214
"name": "python",
190215
"nbconvert_exporter": "python",
191216
"pygments_lexer": "ipython3",
192-
"version": "3.9.7"
217+
"version": "3.7.6"
193218
}
194219
},
195220
"nbformat": 4,

notebooks/NeuroML_Generic_ET/nml2jupyter_ver2.py

Lines changed: 95 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ def __init__(self, path2source, fname_LEMS):
1212

1313
self.path2source = path2source
1414
self.fname_LEMS = fname_LEMS
15-
self.filelist = [] #empty list
16-
self.nmlOutput = {} #empty dictionary
15+
self.filelist = [] #empty list for list of all the files in given NeuroML model
16+
self.trees = [] #empty list for list of all trees for filelist
17+
self.textBox_value_list = [] #empty list for text box widgets having values to be written while updating nml file
18+
self.nmlOutput = {} #empty dictionary for plotting results after running simulation
1719

1820
#function to get list of filenames from LEMS and all subsequent files
1921
def getFileList(self,filename,filelist_local):
@@ -27,8 +29,12 @@ def getFileList(self,filename,filelist_local):
2729
tag_name=child.tag.split("}")[-1] #spliting to remove namespace, if any
2830
if(tag_name.lower()=='include'): #case insensitive search for keyword include
2931
for key, val in child.attrib.items():
30-
if val.endswith('.nml') and val not in filelist_local: #looking for filenames ending with .nml
32+
if val.endswith(('.nml','.xml')) and val not in filelist_local: #looking for filenames ending with .nml or .xml
33+
if os.path.exists(os.path.join(self.path2source,val)): #include only of the file exists in given model source directory
3134
filelist_local=self.getFileList(val,filelist_local)
35+
else:
36+
print('Skipping file : ' + val + ' <- not in source directory')
37+
continue
3238
return filelist_local
3339

3440
#function to parse NeuroML files
@@ -38,16 +44,14 @@ def parseNML(self):
3844
self.filelist=self.getFileList(self.fname_LEMS,[])
3945

4046
#get tree for each of the .nml files
41-
tree=[]
4247
for file in self.filelist:
4348
filename=os.path.join(self.path2source, file)
44-
tree.append(ET.parse(filename))
49+
self.trees.append(ET.parse(filename))
4550

4651
#registering namespace as blank space (some user tag can also be used)
4752
ET.register_namespace("","http://www.neuroml.org/schema/neuroml2")
4853
#ns = {"xmlns":"http://www.neuroml.org/schema/neuroml2"}
4954

50-
return tree
5155

5256
#function to cerate accordion widgets for given root of the xml/nml file
5357
def createAccordions(self,root):
@@ -67,10 +71,13 @@ def createAccordions(self,root):
6771
textBox_key = ipywidgets.Text(value=key,disabled=True,layout=ipywidgets.Layout(width='10%'))
6872
textBox_value = ipywidgets.Text(value=val,layout=ipywidgets.Layout(width='40%'))
6973
textBox_list.append(ipywidgets.HBox([textBox_key, textBox_value]))
70-
74+
self.textBox_value_list.append(textBox_value) #keeping track of textbox widget with values
75+
7176
#for notes tag display a textarea and show text as attributes will be empty
7277
if tag_name=='notes':
73-
textBox_list.append(ipywidgets.Textarea(value=child.text,layout=ipywidgets.Layout(width='50%')))
78+
textArea_text = ipywidgets.Textarea(value=child.text,layout=ipywidgets.Layout(width='50%'))
79+
textBox_list.append(textArea_text)
80+
self.textBox_value_list.append(textArea_text) #keeping track of textbox widget with values
7481

7582
#check if grand child exist
7683
if child:
@@ -89,15 +96,13 @@ def createAccordions(self,root):
8996
return accordion
9097

9198
#Function to generate basic dashboard with tabs and accordions
92-
def generateDashboard(self,trees):
99+
def generateDashboard(self):
93100

94101
tab_list=[] #creating empty tab list
95-
for tree in trees:
102+
for tree in self.trees:
96103
root = tree.getroot()
97104
tab_list.append(self.createAccordions(root)) #add accordions to the tab list
98-
99105
#create a nested tab with accordions
100-
101106
tab_nest = ipywidgets.Tab()
102107
#create tab headers from filenames
103108
for i in range(len(tab_list)):
@@ -107,9 +112,32 @@ def generateDashboard(self,trees):
107112
tab_nest.children = tab_list
108113
display(tab_nest)
109114

110-
#function to update existing NeuroML file based on widget inputs
111-
def writeNMLinputFile(self,C_m, g_Na, g_K, g_L, E_Na, E_K, E_L, t_0, t_n, delta_t, I_inj_max, I_inj_width, I_inj_trans):
112-
print('will do later')
115+
#function to update root of nml file from widget inputs
116+
def nmlWritter(self,root,val_idx):
117+
118+
for child in root:
119+
tag_name=child.tag.split("}")[-1] #spliting to remove namespace, if any
120+
for key, val in child.attrib.items():
121+
child.set(key, self.textBox_value_list[val_idx].value) #setting value from textbox widget
122+
val_idx=val_idx+1
123+
if tag_name=='notes':
124+
child.text=self.textBox_value_list[val_idx].value
125+
val_idx=val_idx+1
126+
if child:
127+
val_idx=self.nmlWritter(child,val_idx)
128+
129+
return val_idx
130+
131+
#function to write NeuroML file based on widget inputs
132+
def writeNMLinputFile(self):
133+
134+
#filelist and trees will be of same length and same order since created by parseNML()
135+
val_idx=0 #index/counter for list of text boxes with values
136+
for file, tree in zip(self.filelist, self.trees):
137+
root = tree.getroot()
138+
val_idx=self.nmlWritter(root,val_idx)
139+
filename=os.path.join(self.path2source, file)
140+
tree.write(filename,xml_declaration=True,encoding='unicode',method='xml')
113141

114142
#function to setup full dashboard/gui
115143
def loadGUI(self):
@@ -118,59 +146,88 @@ def loadGUI(self):
118146
def runNMLmodel(b):
119147
out_log.clear_output()
120148
out_plot.clear_output()
149+
out_validStatus.clear_output()
121150
with out_log:
151+
display('Running NeuroML Model...')
122152
LEMS_file=os.path.join(self.path2source, self.fname_LEMS)
123153
self.nmlOutput = pynml.run_lems_with_jneuroml(LEMS_file, nogui=True, load_saved_data=True)
124154
#shell_cmd=['pynml', LEMS, LEMSoption]
125155
#subprocess.run(shell_cmd)
156+
display('Completed !!!')
126157

127158
#function to validate NeuroML model
128159
def validateNMLmodel(b):
129160
out_log.clear_output()
161+
out_validStatus.clear_output()
130162
with out_log:
163+
display('Validating NeuroML Input Files...')
131164
for file in self.filelist:
132165
if(file.endswith('.nml')):
133166
pathfilename=os.path.join(self.path2source, file)
134-
something=pynml.validate_neuroml2(pathfilename)
167+
checkStatus=pynml.validate_neuroml2(pathfilename)
135168
#shell_cmd=['pynml', pathfilename,'-validate']
136169
#subprocess.run(shell_cmd)
170+
if checkStatus==True:
171+
valid_widget=ipywidgets.Valid(value=True,description='')
172+
with out_validStatus:
173+
display(ipywidgets.HBox([ipywidgets.HTML(value=file,disabled=True),valid_widget]))
174+
else:
175+
valid_widget=ipywidgets.Valid(value=False,description='')
176+
with out_validStatus:
177+
display(ipywidgets.HBox([ipywidgets.HTML(value=file,disabled=True),valid_widget]))
178+
display('Completed !!!')
137179

138180
#function to display plot in notebook
139181
def plotOutput(b):
140182
out_plot.clear_output()
141183
with out_plot:
142184
self.plotData()
185+
186+
#function to update NeuroML files from widget inputs
187+
def updateNMLfiles(b):
188+
out_log.clear_output()
189+
out_plot.clear_output()
190+
out_validStatus.clear_output()
191+
with out_log:
192+
display('Updating NeuroML Files from GUI inputs...')
193+
#display(type(self.filelist),len(self.filelist))
194+
#display(type(self.trees),len(self.trees))
195+
self.writeNMLinputFile()
196+
display('Completed !!!')
143197

144198
#output windows
145-
out_log = ipywidgets.Output(layout={'border': '1px solid'}) #for displaying output log from NeuroMl execution
146-
out_plot = ipywidgets.Output() #for displaying plots
199+
out_log = ipywidgets.Output(layout={'border': '1px solid'}) #for displaying output log from NeuroMl execution
200+
out_plot = ipywidgets.Output() #for displaying plots
201+
out_validStatus = ipywidgets.Output() #for displaying valid widgets after running validate button
147202

148203
ui_widget.run_button.on_click(runNMLmodel)
149204
ui_widget.validate_button.on_click(validateNMLmodel)
150205
ui_widget.plot_button.on_click(plotOutput)
151-
152-
display(ui_widget.buttons,out_log,ui_widget.plot_button,out_plot)
206+
ui_widget.update_button.on_click(updateNMLfiles)
207+
208+
display(ui_widget.buttons,out_validStatus,out_log,ui_widget.plot_button,out_plot)
153209

154210
#function to plot data generated by NeuroML
155211
def plotData(self):
156212
plt.close('all')
157213
for key in self.nmlOutput.keys():
158-
if key == "t":
159-
continue
160-
fig=plt.figure(figsize=(8,2))
161-
fig.canvas.header_visible = False
162-
163-
htmlBox_tittle = ipywidgets.HTML(value='<b><p style="text-align:center">{}</p></b>'.format(key),layout=ipywidgets.Layout(border='solid 1px black',width='60%'))
164-
plt.xlabel("Time (ms)")
165-
plt.ylabel("")
166-
plt.grid(True,linestyle="--")
167-
168-
plt.xlim(min(self.nmlOutput["t"]),max(self.nmlOutput["t"]))
169-
plt.ylim(min(self.nmlOutput[key]),max(self.nmlOutput[key]))
170-
171-
plt.plot(self.nmlOutput["t"], self.nmlOutput[key], linewidth=1)
172-
173-
plotBox=ipywidgets.VBox([htmlBox_tittle,fig.canvas],layout=ipywidgets.Layout(justify_content='center'))
174-
175-
display(plotBox)
214+
if key == "t":
215+
continue
216+
plt.ioff() #suppress plot console window (plot only at display call)
217+
fig=plt.figure(figsize=(8,2))
218+
fig.canvas.header_visible = False
219+
220+
htmlBox_tittle = ipywidgets.HTML(value='<b><p style="text-align:center">{}</p></b>'.format(key),layout=ipywidgets.Layout(border='solid 1px black',width='60%'))
221+
plt.xlabel("Time (ms)")
222+
plt.ylabel("")
223+
plt.grid(True,linestyle="--")
224+
225+
#plt.xlim(min(self.nmlOutput["t"]),max(self.nmlOutput["t"]))
226+
#plt.ylim(min(self.nmlOutput[key]),max(self.nmlOutput[key]))
227+
228+
plt.plot(self.nmlOutput["t"], self.nmlOutput[key], linewidth=1)
229+
230+
plotBox=ipywidgets.VBox([htmlBox_tittle,fig.canvas])
231+
232+
display(plotBox)
176233
#end of class

0 commit comments

Comments
 (0)