Sreenatha is a computer science student at "International Institute of Information Technology, Hyderabad"(IIITH), interested in GUI development for applications(among other things). He is involved in developing the PyGTK GUI of ASCEND.
Subversion account : sreenatha:
GSoC 2012 project : GUI Improvements and Bug Squashing
The original proposal is on the GSoC-melange website.
- Develop the Integrator window
- Add additional features to the PyGTK GUI
- Improve IPython console support to the PyGTK GUI
- Implement the "incidence graph" functionality in windows
- Enable Loading/Saving changed models
- Port the DISPLAY equivalent of the Tcl/Tk GUI to PyGTK GUI
- Add an exit prompt dialog box to the PyGTK GUI
- Bug fixing
- Add a sub menu for selecting display options to the "Diagnose" window
Summary of contributions
- Extended the plot functionality to deal with multi-plot cases
- Improvements to
- Integrator Window
- Implemented unit-awareness for the integrator timesteps and settings
- Made sure that the user's preferred units are shown for these entries
- Diagnose Window
- Option to display default/preferred units for the variables
- Option to display the Diagnose window from the Solver reporter
- Integrator Window
- Added an exit prompt dialog box that pops up while closing the ascend browser
- Added an option to View an ascend model with syntax highlighting
- Fixed bug 273 bug 536 bug 557 bug 558 bug 547 bug 545 and other unreported bugs(see below for more details)
- Patched gtkbrowser.py to ensure that once a delete-event occurs(by clicking on the exit button on title bar), an exit pop-up fires up and asks the user to confirm his exit from the main window i.e, the ASCEND browser.
- Used gtk.MessageDialog instead of gtk.Dialog because according to the docs at pygtk.org, gtk.MessageDialog saves a bit of time when used for trivial purposes(displaying an exit pop-up in this case).
- Ensured that the function do_quit() is called to perform the clean up procedures before exiting.
- Here is the link to the patch http://code.ascend4.org/viewvc/code/branches/sreenatha/pygtk/gtkbrowser.py?r1=4124&r2=4165&view=patch
- Here is an image of the exit pop-up
Feedback from John
- In general I think that an exit popup in ASCEND needs to be a bit smart. Only if a user has manually entered values in to the model and has completed a solution should the exit be confirmed. Otherwise, nothing of particular value has been created, and exiting should be painless/unimpeded.
My proposed solution
- The condition, I'm assuming, that has to be satisfied to trigger the firing up of the exit pop-up is, "Has a model been solved with the values of the variable(s) different from the default ones?". This means that a flag variable has to be added to the __init__ function of 'Browser' class in gtkbrowser.py. This flag variable gets set when the above mentioned condition is satisfied. In the 'exit_popup' function that I've defined, I shall add an if condition that checks if this flag variable is set before displaying the dialog.
- Set the TreeSelection mode of the gtk.TreeView object 'treeview2'(represents Y-axis) in 'PlotDialog' class to gtk.SELECTION_MULTIPLE. The user can now select multiple items from the Y-axis column.
- Used 'get_selected_rows' method instead of 'get_selection' to obtain the selected items of the treeview object because the later was giving errors when the mode of the TreeSelection is set to gtk.SELECTION_MULTIPLE
- Changed the type of self.ycol in 'PlotDialog' class from ObserverColumn to list inorder to account for the multiple columns selected for plotting
- Added a for loop to check if any of the items in the list selected for plotting against Y-axis is the same as the item selected for plotting against X-axis.
- Modified 'plot' function to display the plots of all the items in the list, y, passed as argument. Unfortunately, all the plot figures occur at the same location.
- Selecting three columns to plot in the model dyn_tank.a4c
- Plots for the above selection
- Improved the plotting functionality by restricting the number of figures that can be drawn to one(plots may be multiple)
- If number of plots is 2, the y-axis is provided with two scales(corresponding to the two plots). The two plots are drawn using different styles and can be identified using the legend displayed at the top left and right corners of the graph.
- If number of plots is not 2, the graph has several divisions of plots each of which has a y-axis of it's own. The x-axis is common for all the plots, however. All the y axes are scaled to the same amount.
- As John suggested, grouped the legends towards the upper left corner and made them transparent. Not using the default lineplot of matplotlib because it generates incorrect, non existing data.
- Initially units-unaware, the integrator window now is capable of displaying the units for the integrator timesteps and settings according to user's preferences
- By default, the units in the integrator window's entries are set to the preferred units that the user can select using the Units of Measurement Window
- The user can input any valid units for an integrator parameter using the integrator window and the equivalent value(in preferred units) will be set in the integrator.The entries are tainted if the user inputs invalid units.
- Removed the following line due to inappropriate assumption about the independent variable of the model/simulation.
_t = self.integrator.getCurrentTime( )
- Used the following two lines of code instead
_u = self.indepvar.getInstance().getType().getPreferredUnits() _t = str(self.indepvar.getInstance().getRealValue() / _u.getConversion())
- Found out that 'color_entry' method is actually needed because unlike the properties window, which has the same type of widgets for the inputs, the integrator window has different kinds of widgets(gtk.ComboBox,gtk.Entry) for receiving the data from the user. So, color_entry is called for these entries which donot contain the 'set_property' method used to set the secondary-icon's properties.
- Realized that it is better to set the value and units of the parameters once(when the start button is clicked)rather than many(whenever the entries are changed). In other words, it is better if the code that is responsible for 'setting' the integrator's paremeters is present in 'check_inputs' method(which is called from the 'run' method to check the inputs before running the integrator engine) than the 'parse_entry' method.
- By instantiating the Preferences class, one can get the preferred units of any type by giving as argument, the var type in string format. However, there is a problem with this approach in case of the integrator window. The type of the independent variable in a model/simulation is not known before hand. So, I used a different approach. Here is what I did
- Used the 'getIndependentVariable' method of the integrator instance(self.integrator) to get a 'Variable' class instance(self.indepvar)
- Every member of this 'Variable' class has a method called 'getInstance' which returns an ascpy.Instance object
- From this return value, the var type can be found using the instance's 'getType' method
- Once the type of the variable has been found, there seem to be two ways of getting the preferred units for it.(Fortunately, every solver_var of a similar type in the simulation has to have the same preferred units).
- Use that var type(string) as an argument to getPreferredUnits method of 'Preferences' class-instance which can be generated on the fly.
- Use the method 'getPreferredUnits' of the 'Type' class instance y.getInstance().getType().
- Added 'indepvar' as a variable-member of the IntegratorWindow class but couldn't generate it, on the fly, for two reasons.
- The parse_entry function, which has been reused from properties.py, needs the entry's instance in ascpy.Instance format. This instance, in proper format, can be derived from the indepvar variable. However, this 'Variable' can't be passed to parse_entry due to some weird errors regarding the number of arguments being passed.
- Most of the methods within the IntegratorWindow use the 'indepvar' variable directly or indirectly(for preferred units and stuff). So, argument passing overhead can be avoided by making it accessible to all these methods.
- Added 'parse_entry' as the callback function for 'changed' signal(inherited from gtk.Editable) for the gtk.Entry widgets corresponding to those parameters which have units(Start,Duration,Initial substep, Minimum substep, Maximum substep). Also added the 'taint_entry' method which actually colors the input box depending on the entry. See Image below.
- Patch to the original integrator.py http://code.ascend4.org/viewvc/code/branches/sreenatha/pygtk/integrator.py?r1=4124&r2=4237&view=patch
- Patch to the glade file ascend.glade http://code.ascend4.org/viewvc/code/branches/sreenatha/pygtk/glade/ascend.glade?r1=4209&r2=4243&view=patch. Please note that this patch has to be applied to the glade file present at the directory pointed by the environment variable INSTALL_ASCDATA which the user can set through the terminal.
- Bug 273
- Changed the 'diagnosewin' entry in the glade file(ascend.glade) to accommodate for the additional functionality of showing the units of the variables in the variable entry box in the diagnose window, var_popup and rel_popup.
- Screenshots of ascend running on models/johnpye/pendulum.a4c
- Added, as proposed, a sub-menu for selecting display options similar to the Solver Reporter pop-up. The sub-menu has the following menu items
- Removed these options and reverted to the old style of using the diagnose window as a tool
- Added "Show Block Diagnosis" button to the Solver reporter window so that when a model is solved, the user can view the Diagnose Blocks window in a more intutive manner.
- Added a check button to the diagnose window, as suggested by john, so that the user can choose to have either the default units or the preferred units of the variable displayed(in the variable and relation popups as well).
- The units(if any) displayed in the diagnose window entries will change dynamically when the check box is clicked/unclicked.
- Screenshot of the diagnose window checkbox
- The following code illustrates how the units of the variable 'var' are found depending on the state of the checkbox
units = '' default_units = var.getInstance().getType().getDimensions().getDefaultUnits().getName().toString() pref_units = var.getInstance().getType().getPreferredUnits().getName().toString() if checkbox==set: if pref_units: units = pref_units else: if default_units!='?': units = default_units
- The View window in the PyGTK GUI tries to accomplish what the DISPLAY service in Tcl/Tk GUI does a.k.a display the code for one of the loaded models
- The user has to select a file using a gtk.FileChooserDialog widget that appears after clicking the View item in the toolbar before viewing the model.
- Added tooltips for the menu items of the filemenu(to which the view menu item has been added).
- Image of the view window
- Removed the View menuitem in the File menu due to design issues
- Enabled syntax highlighting for the View window(Referred to canvasproperties.py)
- Updated moduleview.py to support rightclicks on the models and modules in Modules tab
- Upon rightclick on a model of the module or even the module itself, a menu with only one option(View) is displayed. Clicking this menuitem will send a signal to the callback function view_activate which will instantiate the ViewModel class(which defines the View Window that pops up).
- Also added support for viewing ATOM declarations and DEFINITIONs
- Implementation details
- Added view items in the GtkMenuItem with id='filemenu_menu' and the GtkToolbar with id='toolbar3' using the Glade Interface Designer for linux
- Defined callback function 'view_click' in gtkbrowser.py for these added items
- Replicated from 'open_click', the code for displaying the window to choose/select the location of the model, in view_click
- Added a class 'ViewModel' to gtkbrowser.py(changed to modelview.py to enable viewing the models in the 'Models' tab) which defines the view window that displays the actual content of the model/module selected
- gtk.Window for the view window
- gtk.VBox for the vertical box inside the window
- gtk.TextView for the viewing widget
- gtk.ScrolledWindow for the scrollable window
- The view window contains the vertical box container inside which is a scrollable window encapsulating the widget(gtk.TextView) that actually shows the content of the file. Because TextView widget doesn't have scroll-down/up options, it is placed in a scrollable window.
- bug 273
- Initially displayed default units of the selected variable in the Diagnose window and it's variable and relation popups. After discussing with John, switched to showing units of user's choice(default/preferred) based on the check box. See above for images and other details.
- bug 536
- Added the 'Report Bug' button to the Error Info dialog
- Clicking the button will redirect to http://bugs.ascend4.org/login_select_proj_page.php?ref=bug_report_page.php
- Discussed with John, the possibility of submitting the tracevalue of the error to the form in the Bug Report Page using the python module mechanize assuming that the user is already logged in to the ascend bug tracker.
- Feedback from John : I don't think we can depend on the user being logged in to report a bug. I think that 'mechanize' would be overkill/excessive complexity for this problem. Probably it will be easier for us to make modifications to Mantis (the bugtracker software) instead. Perhaps an option would be to output the traceback information such that the user can easily copy-and-paste it into the bug report form. Meanwhile we can ask the Mantis developers on the project selection thing.
- bug 545
- Converted the 'No.of steps' label in the Study window into a dropdown menu containing 'No.of steps' and 'Stepsize'/'Stepratio'
- Developed Unit-awareness for the study window's entries
- By default, the preferred units of the variable to be studied are displayed
- As with the new integrator window, the study window too provides the user with the option of setting any valid units for the study parameters
- The second option in the dropdown menu(the first being 'No. of steps') changes with the selected distribution
- Linear distribution -> Step size
- Logarithmic distribution -> Step ratio
- bug 547
- The integrator window now displays the input with user's preferred units(instead of values in base SI units)
- The actual parameters of the integrator are also set according to the user's input
- See above for further information
- bug 557
- The auto-update-check dialog will now appear only after a week has passed by since the first opening of the pygtk ascend browser
- Added a variable in the 'ascend.ini' preference file that stores the time of the first run. The dialog will pop only if the first run had been atleast a week ago.
- The check will occur, as before, on a weekly basis(unless disabled) after the initial period of one week.
- bug 558
- Stopped the crash that happens when the parser is passed a directory as an argument by performing a pre-check on the command line arguments for hints of a directory path.
- Used ANSI escape sequence to display the error in a coloured format
- Screenshot of the output when the command $./ascend ../models/johnpye was run
- Feedback from John : Is there any way to stop ASCEND from attempting to load the GUI before checking whether or not the file exists?
- It is possible to stop the modules/GUI (that are responsible for option parsing) from loading in the specific case of a single incorrect command line argument. However, if we generalize it to the case of any number of arguments, no option parsing would be done. Without option parsing, we can't be sure whether the given path is an incorrect file address or a correct assets-directory address.
- bug 548
- Stopped the crash that occurs when the model is reloaded with the Integrator tab open
- Made sure that any open integrator which is not currently linked to a simulation is tainted in grey and the add button is disabled
- The Integrator tab gets most of it's functionality from the Observer tab. However, the integrator tab does not have an 'activeiter'(which marks the current active iteration in case of an observer tab). The problem that was occuring was that the activeiter for the integrator was being accessed when a reload occurs. Since, a reference to a NULL object causes an exception, I set the activeiter for integrators to None as accessing a None item does not raise an exception.
- Programming error when integrating a model with no independent variable
- Reduced the overhead of loading the GUI components of the Integrator window from the glade file in the case where there is no independent variable in the model. So, if integration is not possible(i.e, if independent variable is not found in the model), only an error dialog will pop up(when the user clicks on the integrate button) while previously the integrator window got loaded before the error dialog.