@@ -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