4 HOOKE - A force spectroscopy review & analysis tool
6 Copyright (C) 2008-2010 Massimo Sandal (University of Bologna, Italy).
7 Rolf Schmidt (Concordia University, Canada).
9 This program is released under the GNU General Public License version 2.
12 from libhooke import WX_GOOD
15 wxversion.select(WX_GOOD)
29 import wx.lib.agw.aui as aui
30 import wx.propgrid as wxpg
33 from config import config
38 import hookepropertyeditor
44 __version__ = lh.HOOKE_VERSION[0]
45 __release_name__ = lh.HOOKE_VERSION[1]
47 #TODO: order menu items, get rid of all unused IDs
48 ID_ExportText = wx.NewId()
49 ID_ExportImage = wx.NewId()
50 ID_Config = wx.NewId()
53 ID_Previous = wx.NewId()
55 ID_ViewAssistant = wx.NewId()
56 ID_ViewCommands = wx.NewId()
57 ID_ViewFolders = wx.NewId()
58 ID_ViewOutput = wx.NewId()
59 ID_ViewPlaylists = wx.NewId()
60 ID_ViewProperties = wx.NewId()
61 ID_ViewResults = wx.NewId()
63 ID_CommandsList = wx.NewId()
64 ID_CommandsListBox = wx.NewId()
66 ID_TextContent = wx.NewId()
67 ID_TreeContent = wx.NewId()
68 ID_HTMLContent = wx.NewId()
69 ID_SizeReportContent = wx.NewId()
70 ID_DeletePerspective = wx.NewId()
71 ID_SavePerspective = wx.NewId()
73 ID_FirstPerspective = ID_SavePerspective + 1000
74 #I hope we'll never have more than 1000 perspectives
75 ID_FirstPlot = ID_SavePerspective + 2000
80 self.SetAppName('Hooke')
81 self.SetVendorName('')
83 #set the Hooke directory
84 lh.hookeDir = os.path.abspath(os.path.dirname(__file__))
86 windowPosition = (config['main']['left'], config['main']['top'])
87 windowSize = (config['main']['width'], config['main']['height'])
89 #setup the splashscreen
90 if config['splashscreen']['show']:
91 filename = lh.get_file_path('hooke.jpg', ['resources'])
92 if os.path.isfile(filename):
93 bitmap = wx.Image(filename).ConvertToBitmap()
94 splashStyle = wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_TIMEOUT
95 splashDuration = config['splashscreen']['duration']
96 wx.SplashScreen(bitmap, splashStyle, splashDuration, None, -1)
99 we need for the splash screen to disappear
100 for whatever reason splashDuration and sleep do not correspond to each other
101 at least not on Windows
102 maybe it's because duration is in milliseconds and sleep in seconds
103 thus we need to increase the sleep time a bit
104 a factor of 1.2 seems to work quite well
107 time.sleep(sleepFactor * splashDuration / 1000)
110 for plugin in config['plugins']:
111 if config['plugins'][plugin]:
112 filename = ''.join([plugin, '.py'])
113 path = lh.get_file_path(filename, ['plugins'])
114 if os.path.isfile(path):
115 #get the corresponding filename and path
116 plugin_name = ''.join(['plugins.', plugin])
117 module = __import__(plugin_name)
118 #get the file that contains the plugin
119 class_file = getattr(plugins, plugin)
120 #get the class that contains the commands
121 class_object = getattr(class_file, plugin + 'Commands')
122 plugin_objects.append(class_object)
124 def make_command_class(*bases):
125 #create metaclass with plugins and plotmanipulators
126 return type(HookeFrame)("HookeFramePlugged", bases + (HookeFrame,), {})
127 frame = make_command_class(*plugin_objects)(parent=None, id=wx.ID_ANY, title='Hooke', pos=windowPosition, size=windowSize)
129 self.SetTopWindow(frame)
134 #TODO: write values to ini file if necessary
138 class HookeFrame(wx.Frame):
140 def __init__(self, parent, id=-1, title='', pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE|wx.SUNKEN_BORDER|wx.CLIP_CHILDREN):
141 #call parent constructor
142 wx.Frame.__init__(self, parent, id, title, pos, size, style)
144 self.CreateApplicationIcon()
145 #self.configs contains: {the name of the Commands file: corresponding ConfigObj}
147 ##self.playlists contains: {the name of the playlist: [playlist, tabIndex, plotID]}
149 #self.plugins contains: {the name of the plugin: [caption, function]}
151 #self.plotmanipulators list contains: [the name of the plotmanip, function, name of the module]
152 self.plotmanipulators = []
154 #tell FrameManager to manage this frame
155 self._mgr = aui.AuiManager()
156 self._mgr.SetManagedWindow(self)
157 #set the gradient style
158 self._mgr.GetArtProvider().SetMetric(aui.AUI_DOCKART_GRADIENT_TYPE, aui.AUI_GRADIENT_NONE)
159 #set transparent drag
160 self._mgr.SetFlags(self._mgr.GetFlags() ^ aui.AUI_MGR_TRANSPARENT_DRAG)
162 # set up default notebook style
163 self._notebook_style = aui.AUI_NB_DEFAULT_STYLE | aui.AUI_NB_TAB_EXTERNAL_MOVE | wx.NO_BORDER
164 self._notebook_theme = 0
166 #holds the perspectives: {name, [index, perspectiveStr]}
167 self._perspectives = {}
169 # min size for the frame itself isn't completely done.
170 # see the end up FrameManager::Update() for the test
171 # code. For now, just hard code a frame minimum size
172 self.SetMinSize(wx.Size(400, 300))
174 self.panelAssistant = self.CreatePanelAssistant()
175 self.panelCommands = self.CreatePanelCommands()
176 self.panelFolders = self.CreatePanelFolders()
177 self.panelPlaylists = self.CreatePanelPlaylists()
178 self.panelProperties = self.CreatePanelProperties()
179 self.panelOutput = self.CreatePanelOutput()
180 self.panelResults = self.CreatePanelResults()
181 self.plotNotebook = self.CreateNotebook()
182 #self.textCtrlCommandLine=self.CreateCommandLine()
185 self._mgr.AddPane(self.panelFolders, aui.AuiPaneInfo().Name('Folders').Caption('Folders').Left().CloseButton(True).MaximizeButton(False))
186 self._mgr.AddPane(self.panelPlaylists, aui.AuiPaneInfo().Name('Playlists').Caption('Playlists').Left().CloseButton(True).MaximizeButton(False))
187 self._mgr.AddPane(self.plotNotebook, aui.AuiPaneInfo().Name('Plots').CenterPane().PaneBorder(False))
188 self._mgr.AddPane(self.panelCommands, aui.AuiPaneInfo().Name('Commands').Caption('Settings and commands').Right().CloseButton(True).MaximizeButton(False))
189 self._mgr.AddPane(self.panelProperties, aui.AuiPaneInfo().Name('Properties').Caption('Properties').Right().CloseButton(True).MaximizeButton(False))
190 self._mgr.AddPane(self.panelAssistant, aui.AuiPaneInfo().Name('Assistant').Caption('Assistant').Right().CloseButton(True).MaximizeButton(False))
191 self._mgr.AddPane(self.panelOutput, aui.AuiPaneInfo().Name('Output').Caption('Output').Bottom().CloseButton(True).MaximizeButton(False))
192 self._mgr.AddPane(self.panelResults, aui.AuiPaneInfo().Name('Results').Caption('Results').Bottom().CloseButton(True).MaximizeButton(False))
193 #self._mgr.AddPane(self.textCtrlCommandLine, aui.AuiPaneInfo().Name('CommandLine').CaptionVisible(False).Fixed().Bottom().Layer(2).CloseButton(False).MaximizeButton(False))
194 #self._mgr.AddPane(panelBottom, aui.AuiPaneInfo().Name("panelCommandLine").Bottom().Position(1).CloseButton(False).MaximizeButton(False))
196 # add the toolbars to the manager
197 self.toolbar=self.CreateToolBar()
198 self.toolbarNavigation=self.CreateToolBarNavigation()
199 self._mgr.AddPane(self.toolbar, aui.AuiPaneInfo().Name('toolbar').Caption('Toolbar').ToolbarPane().Top().Layer(1).Row(1).LeftDockable(False).RightDockable(False))
200 self._mgr.AddPane(self.toolbarNavigation, aui.AuiPaneInfo().Name('toolbarNavigation').Caption('Navigation').ToolbarPane().Top().Layer(1).Row(1).LeftDockable(False).RightDockable(False))
201 # "commit" all changes made to FrameManager
203 #create the menubar after the panes so that the default perspective
204 #is created with all panes open
206 self.statusbar = self.CreateStatusBar()
208 #TODO: select item on startup (whatever item)
209 #self.listCtrlCommands.Select(0)
210 #self.OnListboxSelect(None)
211 name = self.config['perspectives']['active']
212 menu_item = self.GetPerspectiveMenuItem(name)
213 self.OnRestorePerspective(menu_item)
214 self.playlists = self.panelPlaylists.Playlists
215 #define the list of active drivers
217 for driver in self.config['drivers']:
218 if self.config['drivers'][driver]:
219 #get the corresponding filename and path
220 filename = ''.join([driver, '.py'])
221 path = lh.get_file_path(filename, ['drivers'])
222 #the driver is active for driver[1] == 1
223 if os.path.isfile(path):
224 #driver files are located in the 'drivers' subfolder
225 driver_name = ''.join(['drivers.', driver])
226 module = __import__(driver_name)
227 class_file = getattr(drivers, driver)
228 for command in dir(class_file):
229 if command.endswith('Driver'):
230 self.drivers.append(getattr(class_file, command))
231 #import all active plugins and plotmanips
232 #the plotmanip_functions contains: {the name of the plotmanip: [method, class_object]}
233 plotmanip_functions = {}
234 #add 'general.ini' to self.configs (this is not a plugin and thus must be imported seperately)
235 ini_path = lh.get_file_path('general.ini', ['plugins'])
236 plugin_config = ConfigObj(ini_path)
237 #self.config.merge(plugin_config)
238 self.configs['general'] = plugin_config
239 #make sure we execute _plug_init() for every command line plugin we import
240 for plugin in self.config['plugins']:
241 if self.config['plugins'][plugin]:
242 filename = ''.join([plugin, '.py'])
243 path = lh.get_file_path(filename, ['plugins'])
244 if os.path.isfile(path):
245 #get the corresponding filename and path
246 plugin_name = ''.join(['plugins.', plugin])
249 module = __import__(plugin_name)
250 #prepare the ini file for inclusion
251 ini_path = path.replace('.py', '.ini')
253 plugin_config = ConfigObj(ini_path)
254 #self.config.merge(plugin_config)
255 self.configs[plugin] = plugin_config
257 commands = eval('dir(module.' + plugin+ '.' + plugin + 'Commands)')
258 #keep only commands (ie names that start with 'do_')
259 commands = [command for command in commands if command.startswith('do_')]
261 self.plugins[plugin] = commands
263 #initialize the plugin
264 eval('module.' + plugin+ '.' + plugin + 'Commands._plug_init(self)')
265 except AttributeError:
269 #initialize the commands tree
270 commands = dir(HookeFrame)
271 commands = [command for command in commands if command.startswith('do_')]
273 self.plugins['general'] = commands
274 self.panelCommands.Initialize(self.plugins)
275 for command in dir(self):
276 if command.startswith('plotmanip_'):
277 plotmanip_functions[command] = [command, getattr(self, command)]
278 for name in self.config['plotmanipulators']['names']:
279 if self.config['plotmanipulators'].as_bool(name):
280 command_name = ''.join(['plotmanip_', name])
281 if command_name in plotmanip_functions:
282 self.plotmanipulators.append(plotmanip_functions[command_name])
283 #load default list, if possible
284 self.do_loadlist(self.config['general']['list'])
286 def _BindEvents(self):
287 self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
288 self.Bind(wx.EVT_SIZE, self.OnSize)
289 self.Bind(wx.EVT_CLOSE, self.OnClose)
290 # Show How To Use The Closing Panes Event
291 self.Bind(aui.EVT_AUI_PANE_CLOSE, self.OnPaneClose)
292 self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnNotebookPageClose)
294 self.Bind(wx.EVT_MENU, self.OnClose, id=wx.ID_EXIT)
295 self.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT)
297 self.Bind(wx.EVT_MENU_RANGE, self.OnView, id=ID_ViewAssistant, id2=ID_ViewResults)
299 self.Bind(wx.EVT_MENU, self.OnDeletePerspective, id=ID_DeletePerspective)
300 self.Bind(wx.EVT_MENU, self.OnSavePerspective, id=ID_SavePerspective)
301 self.Bind(wx.EVT_MENU_RANGE, self.OnRestorePerspective, id=ID_FirstPerspective, id2=ID_FirstPerspective+1000)
303 self.Bind(wx.EVT_TOOL, self.OnExportImage, id=ID_ExportImage)
304 self.Bind(wx.EVT_TOOL, self.OnNext, id=ID_Next)
305 self.Bind(wx.EVT_TOOL, self.OnPrevious, id=ID_Previous)
306 #self.Bind(.EVT_AUITOOLBAR_TOOL_DROPDOWN, self.OnDropDownToolbarItem, id=ID_DropDownToolbarItem)
308 treeCtrl = self.panelFolders.GetTreeCtrl()
309 #tree.Bind(wx.EVT_LEFT_UP, self.OnDirCtrl1LeftUp)
310 #tree.Bind(wx.EVT_LEFT_DOWN, self.OnGenericDirCtrl1LeftDown)
311 treeCtrl.Bind(wx.EVT_LEFT_DCLICK, self.OnDirCtrlLeftDclick)
313 self.panelPlaylists.PlaylistsTree.Bind(wx.EVT_LEFT_DOWN, self.OnPlaylistsLeftDown)
314 self.panelPlaylists.PlaylistsTree.Bind(wx.EVT_LEFT_DCLICK, self.OnPlaylistsLeftDclick)
316 self.panelCommands.ExecuteButton.Bind(wx.EVT_BUTTON, self.OnExecute)
317 self.panelCommands.CommandsTree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeCtrlCommandsLeftDown)
319 self.panelProperties.pg.Bind(wxpg.EVT_PG_CHANGED, self.OnPropGridChanged)
320 self.panelProperties.pg.Bind(wxpg.EVT_PG_SELECTED, self.OnPropGridSelect)
322 self.panelResults.results_list.OnCheckItem = self.OnResultsCheck
324 def _GetActiveCurveIndex(self):
325 playlist = self.GetActivePlaylist()
326 #get the selected item from the tree
327 selected_item = self.panelPlaylists.PlaylistsTree.GetSelection()
328 #test if a playlist or a curve was double-clicked
329 if self.panelPlaylists.PlaylistsTree.ItemHasChildren(selected_item):
333 selected_item = self.panelPlaylists.PlaylistsTree.GetPrevSibling(selected_item)
334 while selected_item.IsOk():
336 selected_item = self.panelPlaylists.PlaylistsTree.GetPrevSibling(selected_item)
339 def _GetActivePlaylistName(self):
340 #get the selected item from the tree
341 selected_item = self.panelPlaylists.PlaylistsTree.GetSelection()
342 #test if a playlist or a curve was double-clicked
343 if self.panelPlaylists.PlaylistsTree.ItemHasChildren(selected_item):
344 playlist_item = selected_item
346 #get the name of the playlist
347 playlist_item = self.panelPlaylists.PlaylistsTree.GetItemParent(selected_item)
348 #now we have a playlist
349 return self.panelPlaylists.PlaylistsTree.GetItemText(playlist_item)
351 def _GetPlaylistTab(self, name):
352 for index, page in enumerate(self.plotNotebook._tabs._pages):
353 if page.caption == name:
357 def _GetUniquePlaylistName(self, name):
360 while playlist_name in self.playlists:
361 playlist_name = ''.join([name, str(count)])
365 def _SavePerspectiveToFile(self, name, perspective):
366 filename = ''.join([name, '.txt'])
367 filename = lh.get_file_path(filename, ['perspectives'])
368 perspectivesFile = open(filename, 'w')
369 perspectivesFile.write(perspective)
370 perspectivesFile.close()
372 def AddPlaylist(self, playlist=None, name='Untitled'):
373 #TODO: change cursor or progressbar (maybe in statusbar)
374 #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
375 if playlist and playlist.count > 0:
376 playlist.name = self._GetUniquePlaylistName(name)
378 self.AddToPlaylists(playlist)
380 def AddPlaylistFromFiles(self, files=[], name='Untitled'):
381 #TODO: change cursor or progressbar (maybe in statusbar)
382 #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
384 playlist = Playlist.Playlist(self.drivers)
386 playlist.add_curve(item)
387 if playlist.count > 0:
388 playlist.name = self._GetUniquePlaylistName(name)
390 self.AddToPlaylists(playlist)
392 def AddToPlaylists(self, playlist):
393 if playlist.has_curves:
394 #setup the playlist in the Playlist tree
395 tree_root = self.panelPlaylists.PlaylistsTree.GetRootItem()
396 playlist_root = self.panelPlaylists.PlaylistsTree.AppendItem(tree_root, playlist.name, 0)
397 #add all curves to the Playlist tree
399 for index, curve in enumerate(playlist.curves):
400 ##remove the extension from the name of the curve
402 #item_text, extension = os.path.splitext(curve.name)
403 #curve_ID = self.panelPlaylists.PlaylistsTree.AppendItem(playlist_root, item_text, 1)
404 curve_ID = self.panelPlaylists.PlaylistsTree.AppendItem(playlist_root, curve.name, 1)
405 if index == playlist.index:
406 self.panelPlaylists.PlaylistsTree.SelectItem(curve_ID)
408 #create the plot tab and add playlist to the dictionary
409 plotPanel = wxmpl.PlotPanel(self, ID_FirstPlot + len(self.playlists))
410 notebook_tab = self.plotNotebook.AddPage(plotPanel, playlist.name, True)
411 tab_index = self.plotNotebook.GetSelection()
412 figure = plotPanel.get_figure()
413 self.playlists[playlist.name] = [playlist, figure]
414 self.panelPlaylists.PlaylistsTree.Expand(playlist_root)
415 self.statusbar.SetStatusText(playlist.get_status_string(), 0)
418 def AppendToOutput(self, text):
419 self.panelOutput.AppendText(''.join([text, '\n']))
421 def CreateApplicationIcon(self):
422 iconFile = 'resources' + os.sep + 'microscope.ico'
423 icon = wx.Icon(iconFile, wx.BITMAP_TYPE_ICO)
426 def CreateCommandLine(self):
427 return wx.TextCtrl(self, -1, '', style=wx.NO_BORDER|wx.EXPAND)
429 def CreatePanelAssistant(self):
430 panel = wx.TextCtrl(self, -1, '', wx.Point(0, 0), wx.Size(150, 90), wx.NO_BORDER|wx.TE_MULTILINE)
431 panel.SetEditable(False)
434 def CreatePanelCommands(self):
435 return hookecommands.Commands(self)
437 def CreatePanelFolders(self):
439 filters = self.config['folders']['filters']
440 index = self.config['folders'].as_int('filterindex')
441 #set initial directory
442 folder = self.config['general']['workdir']
443 return wx.GenericDirCtrl(self, -1, dir=folder, size=(200, 250), style=wx.DIRCTRL_SHOW_FILTERS, filter=filters, defaultFilter=index)
445 def CreatePanelOutput(self):
446 return wx.TextCtrl(self, -1, '', wx.Point(0, 0), wx.Size(150, 90), wx.NO_BORDER|wx.TE_MULTILINE)
448 def CreatePanelPlaylists(self):
449 return hookeplaylist.Playlists(self)
451 def CreatePanelProperties(self):
452 return hookepropertyeditor.PropertyEditor(self)
454 def CreatePanelResults(self):
455 return hookeresults.Results(self)
457 def CreatePanelWelcome(self):
458 ctrl = wx.html.HtmlWindow(self, -1, wx.DefaultPosition, wx.Size(400, 300))
459 introStr = '<h1>Welcome to Hooke</h1>' + \
460 '<h3>Features</h3>' + \
462 '<li>View, annotate, measure force curves</li>' + \
463 '<li>Worm-like chain fit of force peaks</li>' + \
464 '<li>Automatic convolution-based filtering of empty curves</li>' + \
465 '<li>Automatic fit and measurement of multiple force peaks</li>' + \
466 '<li>Handles force-clamp force experiments (experimental)</li>' + \
467 '<li>It is extensible by users by means of plugins and drivers</li>' + \
469 '<p>See the <a href="/p/hooke/wiki/DocumentationIndex">DocumentationIndex</a> for more information</p>'
470 ctrl.SetPage(introStr)
473 def CreateMenuBar(self):
474 menu_bar = wx.MenuBar()
476 file_menu = wx.Menu()
477 file_menu.Append(wx.ID_OPEN, '&Open playlist\tCtrl-O')
478 file_menu.Append(wx.ID_SAVE, 'Save playlist\tCtrl-S')
479 file_menu.AppendSeparator()
480 file_menu.Append(wx.ID_EXIT, 'Exit\tCtrl-Q')
482 edit_menu = wx.Menu()
483 edit_menu.Append(ID_ExportText, 'Export text...')
484 edit_menu.Append(ID_ExportImage, 'Export image...')
485 edit_menu.AppendSeparator();
486 edit_menu.Append(ID_Config, 'Preferences')
488 view_menu = wx.Menu()
489 view_menu.AppendCheckItem(ID_ViewFolders, 'Folders\tF5')
490 view_menu.AppendCheckItem(ID_ViewPlaylists, 'Playlists\tF6')
491 view_menu.AppendCheckItem(ID_ViewCommands, 'Commands\tF7')
492 view_menu.AppendCheckItem(ID_ViewProperties, 'Properties\tF8')
493 view_menu.AppendCheckItem(ID_ViewAssistant, 'Assistant\tF9')
494 view_menu.AppendCheckItem(ID_ViewResults, 'Results\tF10')
495 view_menu.AppendCheckItem(ID_ViewOutput, 'Output\tF11')
497 self._perspectives_menu = self.CreatePerspectivesMenu()
499 help_menu = wx.Menu()
500 help_menu.Append(wx.ID_ABOUT, 'About Hooke')
502 menu_bar.Append(file_menu, 'File')
503 menu_bar.Append(edit_menu, 'Edit')
504 menu_bar.Append(view_menu, 'View')
505 menu_bar.Append(self._perspectives_menu, "Perspectives")
506 menu_bar.Append(help_menu, 'Help')
508 self.SetMenuBar(menu_bar)
510 def CreateNotebook(self):
511 # create the notebook off-window to avoid flicker
512 client_size = self.GetClientSize()
513 ctrl = aui.AuiNotebook(self, -1, wx.Point(client_size.x, client_size.y), wx.Size(430, 200), self._notebook_style)
514 arts = [aui.AuiDefaultTabArt, aui.AuiSimpleTabArt, aui.VC71TabArt, aui.FF2TabArt, aui.VC8TabArt, aui.ChromeTabArt]
515 art = arts[self._notebook_theme]()
516 ctrl.SetArtProvider(art)
517 #uncomment if we find a nice icon
518 #page_bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, wx.Size(16, 16))
519 ctrl.AddPage(self.CreatePanelWelcome(), "Welcome", False)
522 def CreatePerspectivesMenu(self):
524 menu.Append(ID_SavePerspective, "Save Perspective")
525 menu.Append(ID_DeletePerspective, "Delete Perspective")
526 menu.AppendSeparator()
527 #add perspectives to menubar and _perspectives
528 perspectivesDirectory = os.path.join(lh.hookeDir, 'perspectives')
529 if os.path.isdir(perspectivesDirectory):
530 perspectiveFileNames = os.listdir(perspectivesDirectory)
531 for perspectiveFilename in perspectiveFileNames:
532 filename = lh.get_file_path(perspectiveFilename, ['perspectives'])
533 if os.path.isfile(filename):
534 perspectiveFile = open(filename, 'rU')
535 perspective = perspectiveFile.readline()
536 perspectiveFile.close()
537 if perspective != '':
538 name, extension = os.path.splitext(perspectiveFilename)
539 if extension == '.txt':
540 menuItem = menu.AppendRadioItem(ID_FirstPerspective + len(self._perspectives), name)
541 self._perspectives[name] = [len(self._perspectives), perspective]
542 if self.config['perspectives']['active'] == name:
544 #in case there are no perspectives
545 if not self._perspectives:
546 perspective = self._mgr.SavePerspective()
547 self.config['perspectives']['default'] = 'Default'
548 self._perspectives['Default'] = [0, perspective]
549 menuItem = menu.AppendRadioItem(ID_FirstPerspective, 'Default')
551 self._SavePerspectiveToFile('Default', perspective)
554 def CreateStatusbar(self):
555 statusbar = self.CreateStatusBar(2, wx.ST_SIZEGRIP)
556 statusbar.SetStatusWidths([-2, -3])
557 statusbar.SetStatusText('Ready', 0)
558 welcomeString=u'Welcome to Hooke (version '+__version__+', '+__release_name__+')!'
559 statusbar.SetStatusText(welcomeString, 1)
562 def CreateToolBar(self):
563 toolbar = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_FLAT | wx.TB_NODIVIDER)
564 toolbar.SetToolBitmapSize(wx.Size(16,16))
565 toolbar_bmp1 = wx.ArtProvider_GetBitmap(wx.ART_QUESTION, wx.ART_OTHER, wx.Size(16, 16))
566 toolbar_bmpOpen = wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, wx.Size(16, 16))
567 toolbar_bmpSave = wx.ArtProvider_GetBitmap(wx.ART_FILE_SAVE, wx.ART_OTHER, wx.Size(16, 16))
568 toolbar_bmpExportText = wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, wx.Size(16, 16))
569 toolbar_bmpExportImage = wx.ArtProvider_GetBitmap(wx.ART_MISSING_IMAGE, wx.ART_OTHER, wx.Size(16, 16))
570 toolbar.AddLabelTool(101, 'Open', toolbar_bmpOpen)
571 toolbar.AddLabelTool(102, 'Save', toolbar_bmpSave)
572 toolbar.AddSeparator()
573 toolbar.AddLabelTool(ID_ExportText, 'Export text...', toolbar_bmpExportText)
574 toolbar.AddLabelTool(ID_ExportImage, 'Export image...', toolbar_bmpExportImage)
578 def CreateToolBarNavigation(self):
579 toolbar = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_FLAT | wx.TB_NODIVIDER)
580 toolbar.SetToolBitmapSize(wx.Size(16,16))
581 toolbar_bmpBack = wx.ArtProvider_GetBitmap(wx.ART_GO_BACK, wx.ART_OTHER, wx.Size(16, 16))
582 toolbar_bmpForward = wx.ArtProvider_GetBitmap(wx.ART_GO_FORWARD, wx.ART_OTHER, wx.Size(16, 16))
583 toolbar.AddLabelTool(ID_Previous, 'Previous', toolbar_bmpBack, shortHelp='Previous curve')
584 toolbar.AddLabelTool(ID_Next, 'Next', toolbar_bmpForward, shortHelp='Next curve')
588 def DeleteFromPlaylists(self, name):
589 if name in self.playlists:
590 del self.playlists[name]
591 tree_root = self.panelPlaylists.PlaylistsTree.GetRootItem()
592 item, cookie = self.panelPlaylists.PlaylistsTree.GetFirstChild(tree_root)
594 playlist_name = self.panelPlaylists.PlaylistsTree.GetItemText(item)
595 if playlist_name == name:
597 self.panelPlaylists.PlaylistsTree.Delete(item)
600 item = self.panelPlaylists.PlaylistsTree.GetNextSibling(item)
601 self.OnPlaylistsLeftDclick(None)
603 def DeletePlotPage(self, name):
604 index = self._GetPlaylistTab(name)
605 plot = self.playlists[name][1]
607 self.plotNotebook.RemovePage(index)
608 self.DeleteFromPlaylists(name)
610 def GetActiveCurve(self):
611 playlist = self.GetActivePlaylist()
612 if playlist is not None:
613 return playlist.get_active_curve()
616 def GetActivePlaylist(self):
617 playlist_name = self._GetActivePlaylistName()
618 if playlist_name in self.playlists:
619 return self.playlists[playlist_name][0]
622 def GetActivePlot(self):
623 curve = self.GetActiveCurve()
624 if curve is not None:
625 return curve.plots[0]
628 def GetDockArt(self):
629 return self._mgr.GetArtProvider()
631 def GetBoolFromConfig(self, *args):
640 if self.configs.has_key(plugin):
641 config = self.configs[plugin]
642 return config[section][key].as_bool('value')
645 def GetFloatFromConfig(self, *args):
654 if self.configs.has_key(plugin):
655 config = self.configs[plugin]
656 return config[section][key].as_float('value')
659 def GetIntFromConfig(self, *args):
668 if self.configs.has_key(plugin):
669 config = self.configs[plugin]
670 return config[section][key].as_int('value')
673 def GetStringFromConfig(self, *args):
682 if self.configs.has_key(plugin):
683 config = self.configs[plugin]
684 return config[section][key]['value']
687 def GetPerspectiveMenuItem(self, name):
688 index = self._perspectives[name][0]
689 perspective_Id = ID_FirstPerspective + index
690 menu_item = self.MenuBar.FindItemById(perspective_Id)
693 def HasPlotmanipulator(self, name):
695 returns True if the plotmanipulator 'name' is loaded, False otherwise
697 for plotmanipulator in self.plotmanipulators:
698 if plotmanipulator[0] == name:
702 def OnAbout(self, event):
704 'A free, open source data analysis platform\n'+\
705 '(c) 2006-2008 Massimo Sandal\n\n'+\
706 '(c) 2009 Dr. Rolf Schmidt\n\n'+\
707 'Released under the GNU GPL v2'
708 dialog = wx.MessageDialog(self, msg, "About Hooke", wx.OK | wx.ICON_INFORMATION)
712 def OnClose(self, event):
714 self.config['main']['height'] = str(self.GetSize().GetHeight())
715 self.config['main']['left'] = str(self.GetPosition()[0])
716 self.config['main']['top'] = str(self.GetPosition()[1])
717 self.config['main']['width'] = str(self.GetSize().GetWidth())
718 # Writing the configuration file to 'hooke.ini'
724 def OnDeletePerspective(self, event):
727 def OnDirCtrlLeftDclick(self, event):
728 file_path = self.panelFolders.GetPath()
729 if os.path.isfile(file_path):
730 if file_path.endswith('.hkp'):
731 self.do_loadlist(file_path)
736 def OnEraseBackground(self, event):
739 def OnExecute(self, event):
740 item = self.panelCommands.CommandsTree.GetSelection()
742 if self.panelCommands.CommandsTree.ItemHasChildren(item):
746 parent = self.panelCommands.CommandsTree.GetItemParent(item)
747 if not self.panelCommands.CommandsTree.ItemHasChildren(item):
748 parent_text = self.panelCommands.CommandsTree.GetItemText(parent)
749 item_text = self.panelCommands.CommandsTree.GetItemText(item)
750 if item_text in ['genlist', 'loadlist', 'savelist']:
751 property_values = self.panelProperties.GetPropertyValues()
753 for item in property_values:
754 arg_str = ''.join([arg_str, item, '=r"', str(property_values[item]), '", '])
755 command = ''.join(['self.do_', item_text, '(', arg_str, ')'])
757 command = ''.join(['self.do_', item_text, '()'])
761 def OnExit(self, event):
764 def OnExportImage(self, event):
767 def OnNext(self, event):
770 Go to the next curve in the playlist.
771 If we are at the last curve, we come back to the first.
775 selected_item = self.panelPlaylists.PlaylistsTree.GetSelection()
776 if self.panelPlaylists.PlaylistsTree.ItemHasChildren(selected_item):
777 #GetFirstChild returns a tuple
778 #we only need the first element
779 next_item = self.panelPlaylists.PlaylistsTree.GetFirstChild(selected_item)[0]
781 next_item = self.panelPlaylists.PlaylistsTree.GetNextSibling(selected_item)
782 if not next_item.IsOk():
783 parent_item = self.panelPlaylists.PlaylistsTree.GetItemParent(selected_item)
784 #GetFirstChild returns a tuple
785 #we only need the first element
786 next_item = self.panelPlaylists.PlaylistsTree.GetFirstChild(parent_item)[0]
787 self.panelPlaylists.PlaylistsTree.SelectItem(next_item, True)
788 playlist = self.playlists[self._GetActivePlaylistName()][0]
789 if playlist.count > 1:
791 self.statusbar.SetStatusText(playlist.get_status_string(), 0)
794 def OnNotebookPageClose(self, event):
795 ctrl = event.GetEventObject()
796 playlist_name = ctrl.GetPageText(ctrl._curpage)
797 self.DeleteFromPlaylists(playlist_name)
799 def OnPaneClose(self, event):
802 def OnPlaylistsLeftDclick(self, event):
803 playlist_name = self._GetActivePlaylistName()
804 #if that playlist already exists
805 #we check if it is the active playlist (ie selected in panelPlaylists)
806 #and switch to it if necessary
807 if playlist_name in self.playlists:
808 index = self.plotNotebook.GetSelection()
809 current_playlist = self.plotNotebook.GetPageText(index)
810 #new_playlist = self.playlists[playlist_name][0]
811 #if current_playlist != new_playlist:
812 if current_playlist != playlist_name:
813 index = self._GetPlaylistTab(playlist_name)
814 self.plotNotebook.SetSelection(index)
815 #if a curve was double-clicked
816 item = self.panelPlaylists.PlaylistsTree.GetSelection()
817 #TODO: fix with get_active_curve
818 if not self.panelPlaylists.PlaylistsTree.ItemHasChildren(item):
819 index = self._GetActiveCurveIndex()
823 playlist = self.playlists[playlist_name][0]
824 playlist.index = index
825 self.statusbar.SetStatusText(playlist.get_status_string(), 0)
827 #if you uncomment the following line, the tree will collapse/expand as well
830 def OnPlaylistsLeftDown(self, event):
831 hit_item, hit_flags = self.panelPlaylists.PlaylistsTree.HitTest(event.GetPosition())
832 if (hit_flags & wx.TREE_HITTEST_ONITEM) != 0:
834 self.panelPlaylists.PlaylistsTree.SelectItem(hit_item)
835 playlist_name = self._GetActivePlaylistName()
836 playlist = self.playlists[playlist_name][0]
837 #if a curve was clicked
838 item = self.panelPlaylists.PlaylistsTree.GetSelection()
839 if not self.panelPlaylists.PlaylistsTree.ItemHasChildren(item):
840 #TODO: fix with get_active_curve
841 index = self._GetActiveCurveIndex()
843 #playlist = self.playlists[playlist_name][0]
844 playlist.index = index
845 #self.playlists[playlist_name][0].index = index
847 ##self.playlists[playlist_name][0].index = 0
848 #playlist.index = index
849 self.playlists[playlist_name][0] = playlist
852 def OnPrevious(self, event):
855 Go to the previous curve in the playlist.
856 If we are at the first curve, we jump to the last.
860 #playlist = self.playlists[self._GetActivePlaylistName()][0]
861 #select the previous curve and tell the user if we wrapped around
862 #self.AppendToOutput(playlist.previous())
863 selected_item = self.panelPlaylists.PlaylistsTree.GetSelection()
864 if self.panelPlaylists.PlaylistsTree.ItemHasChildren(selected_item):
865 previous_item = self.panelPlaylists.PlaylistsTree.GetLastChild(selected_item)
867 previous_item = self.panelPlaylists.PlaylistsTree.GetPrevSibling(selected_item)
868 if not previous_item.IsOk():
869 parent_item = self.panelPlaylists.PlaylistsTree.GetItemParent(selected_item)
870 previous_item = self.panelPlaylists.PlaylistsTree.GetLastChild(parent_item)
871 self.panelPlaylists.PlaylistsTree.SelectItem(previous_item, True)
872 playlist = self.playlists[self._GetActivePlaylistName()][0]
873 if playlist.count > 1:
875 self.statusbar.SetStatusText(playlist.get_status_string(), 0)
878 def OnPropGridChanged (self, event):
879 prop = event.GetProperty()
881 item_section = self.panelProperties.SelectedTreeItem
882 item_plugin = self.panelCommands.CommandsTree.GetItemParent(item_section)
883 plugin = self.panelCommands.CommandsTree.GetItemText(item_plugin)
884 config = self.configs[plugin]
885 property_section = self.panelCommands.CommandsTree.GetItemText(item_section)
886 property_key = prop.GetName()
887 property_value = prop.GetValue()
888 config[property_section][property_key]['value'] = property_value
890 def OnPropGridSelect(self, event):
893 def OnRestorePerspective(self, event):
894 name = self.MenuBar.FindItemById(event.GetId()).GetLabel()
895 self._mgr.LoadPerspective(self._perspectives[name][1])
896 self.config['perspectives']['active'] = name
898 all_panes = self._mgr.GetAllPanes()
899 for pane in all_panes:
900 if not pane.name.startswith('toolbar'):
901 if pane.name == 'Assistant':
902 self.MenuBar.FindItemById(ID_ViewAssistant).Check(pane.window.IsShown())
903 if pane.name == 'Folders':
904 self.MenuBar.FindItemById(ID_ViewFolders).Check(pane.window.IsShown())
905 if pane.name == 'Playlists':
906 self.MenuBar.FindItemById(ID_ViewPlaylists).Check(pane.window.IsShown())
907 if pane.name == 'Commands':
908 self.MenuBar.FindItemById(ID_ViewCommands).Check(pane.window.IsShown())
909 if pane.name == 'Properties':
910 self.MenuBar.FindItemById(ID_ViewProperties).Check(pane.window.IsShown())
911 if pane.name == 'Output':
912 self.MenuBar.FindItemById(ID_ViewOutput).Check(pane.window.IsShown())
913 if pane.name == 'Results':
914 self.MenuBar.FindItemById(ID_ViewResults).Check(pane.window.IsShown())
916 def OnResultsCheck(self, index, flag):
917 curve = self.GetActiveCurve()
918 result = curve.data['results'][index]['visible'] = flag
921 def OnSavePerspective(self, event):
922 def nameExists(name):
923 for item in self._perspectives_menu.GetMenuItems():
924 if item.GetText() == name:
930 dialog = wx.TextEntryDialog(self, 'Enter a name for the new perspective:', 'Save perspective')
931 dialog.SetValue('New perspective')
932 if dialog.ShowModal() != wx.ID_OK:
935 name = dialog.GetValue()
938 dialogConfirm = wx.MessageDialog(self, 'A file with this name already exists.\n\nDo you want to replace it?', 'Confirm', wx.YES_NO|wx.ICON_QUESTION|wx.CENTER)
939 if dialogConfirm.ShowModal() == wx.ID_YES:
944 perspective = self._mgr.SavePerspective()
947 #check the corresponding menu item
948 menuItem = self.GetPerspectiveMenuItem(name)
949 #replace the perspectiveStr in _pespectives
950 index = self._perspectives[name][0]
951 self._perspectives[name] = [index, perspective]
953 #simply add the new perspective to _perspectives
954 index = len(self._perspectives)
955 self._perspectives[name] = [len(self._perspectives), perspective]
956 menuItem = self._perspectives_menu.AppendRadioItem(ID_FirstPerspective + len(self._perspectives), name)
959 self._SavePerspectiveToFile(name, perspective)
960 #uncheck all perspective menu items
961 #as these are radio items, one item has to be checked at all times
962 #the line 'menuItem.Check()' above actually checks a second item
964 #so we need to uncheck all other items afterwards
965 #weirdly enough, menuitem.Toggle() doesn't do this properly either
966 for item in self._perspectives_menu.GetMenuItems():
967 if item.IsCheckable():
968 if item.GetLabel() != name:
971 def OnView(self, event):
972 menu_id = event.GetId()
973 menu_item = self.MenuBar.FindItemById(menu_id)
974 menu_label = menu_item.GetLabel()
976 pane = self._mgr.GetPane(menu_label)
977 pane.Show(not pane.IsShown())
978 #if we don't do the following, the Folders pane does not resize properly on hide/show
979 if pane.caption == 'Folders' and pane.IsShown() and pane.IsDocked():
980 #folders_size = pane.GetSize()
981 self.panelFolders.Fit()
984 def OnSize(self, event):
987 def OnTreeCtrlCommandsLeftDown(self, event):
988 hit_item, hit_flags = self.panelCommands.CommandsTree.HitTest(event.GetPosition())
989 if (hit_flags & wx.TREE_HITTEST_ONITEM) != 0:
990 self.panelCommands.CommandsTree.SelectItem(hit_item)
991 self.panelProperties.SelectedTreeItem = hit_item
992 #if a command was clicked
994 if not self.panelCommands.CommandsTree.ItemHasChildren(hit_item):
995 item_plugin = self.panelCommands.CommandsTree.GetItemParent(hit_item)
996 plugin = self.panelCommands.CommandsTree.GetItemText(item_plugin)
997 if self.configs.has_key(plugin):
998 #config = self.panelCommands.CommandsTree.GetPyData(item_plugin)
999 config = self.configs[plugin]
1000 section = self.panelCommands.CommandsTree.GetItemText(hit_item)
1001 #display docstring in help window
1002 doc_string = eval('self.do_' + section + '.__doc__')
1003 if section in config:
1004 for option in config[section]:
1005 properties.append([option, config[section][option]])
1007 module = self.panelCommands.CommandsTree.GetItemText(hit_item)
1008 if module != 'general':
1009 doc_string = eval('plugins.' + module + '.' + module + 'Commands.__doc__')
1011 doc_string = 'The module "general" contains Hooke core functionality'
1012 if doc_string is not None:
1013 self.panelAssistant.ChangeValue(doc_string)
1014 hookepropertyeditor.PropertyEditor.Initialize(self.panelProperties, properties)
1017 def UpdatePlaylists(self):
1018 #setup the playlist in the Playlist tree
1019 tree_root = self.panelPlaylists.PlaylistsTree.GetRootItem()
1020 playlist_root = self.panelPlaylists.PlaylistsTree.AppendItem(tree_root, playlist.name, 0)
1021 #add all curves to the Playlist tree
1023 for index, curve in enumerate(playlist.curves):
1024 ##remove the extension from the name of the curve
1026 #item_text, extension = os.path.splitext(curve.name)
1027 #curve_ID = self.panelPlaylists.PlaylistsTree.AppendItem(playlist_root, item_text, 1)
1028 curve_ID = self.panelPlaylists.PlaylistsTree.AppendItem(playlist_root, curve.name, 1)
1029 if index == playlist.index:
1030 self.panelPlaylists.PlaylistsTree.SelectItem(curve_ID)
1031 #create the plot tab and add playlist to the dictionary
1032 plotPanel = wxmpl.PlotPanel(self, ID_FirstPlot + len(self.playlists))
1033 notebook_tab = self.plotNotebook.AddPage(plotPanel, playlist.name, True)
1034 #tab_index = self.plotNotebook.GetSelection()
1035 figure = plotPanel.get_figure()
1036 #self.playlists[playlist.name] = [playlist, tab_index, figure]
1037 self.playlists[playlist.name] = [playlist, figure]
1038 self.panelPlaylists.PlaylistsTree.Expand(playlist_root)
1039 self.statusbar.SetStatusText(playlist.get_status_string(), 0)
1043 #Everything sending an event should be here
1044 def _measure_N_points(self, N, whatset=1):
1046 general helper function for N-points measures
1048 wx.PostEvent(self.frame,self.list_of_events['measure_points'](num_of_points=N, set=whatset))
1051 points=self.frame.events_from_gui.get()
1057 def _clickize(self, xvector, yvector, index):
1059 returns a ClickedPoint() object from an index and vectors of x, y coordinates
1061 point = lh.ClickedPoint()
1063 point.absolute_coords = xvector[index], yvector[index]
1064 point.find_graph_coords(xvector, yvector)
1067 #PLAYLIST INTERACTION COMMANDS
1068 #-------------------------------
1069 def do_genlist(self, folder=lh.hookeDir, filemask='*.*'):
1072 Generates a file playlist.
1073 Note it doesn't *save* it: see savelist for this.
1075 If [input files] is a directory, it will use all files in the directory for playlist.
1081 are all equivalent syntax.
1083 Syntax: genlist [input files]
1085 #args list is: input folder, file mask
1086 if os.path.isdir(folder):
1087 path = os.path.join(folder, filemask)
1088 #expanding correctly the input list with the glob module :)
1089 files = glob.glob(path)
1091 #TODO: change cursor or progressbar (maybe in statusbar)
1092 #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
1093 playlist = playlist.Playlist(self.drivers)
1095 curve = playlist.add_curve(item)
1096 plot = copy.deepcopy(curve.plots[0])
1098 curve.add_data('raw', plot.vectors[0][0], plot.vectors[0][1], color=plot.colors[0], style='plot')
1099 curve.add_data('raw', plot.vectors[1][0], plot.vectors[1][1], color=plot.colors[1], style='plot')
1100 #apply all active plotmanipulators and add the 'manipulated' data
1101 for plotmanipulator in self.plotmanipulators:
1102 plot = plotmanipulator[1](plot, curve)
1103 curve.set_data('manipulated', plot.vectors[0][0], plot.vectors[0][1], color=plot.colors[0], style='plot')
1104 curve.add_data('manipulated', plot.vectors[1][0], plot.vectors[1][1], color=plot.colors[1], style='plot')
1105 if playlist.count > 0:
1106 playlist.name = self._GetUniquePlaylistName(os.path.basename(folder))
1108 self.AddToPlaylists(playlist)
1109 self.AppendToOutput(playlist.get_status_string())
1111 self.AppendToOutput(''.join(['Cannot find folder ', folder]))
1113 def do_loadlist(self, filename):
1116 Loads a file playlist
1118 Syntax: loadlist [playlist file]
1120 #TODO: check for duplicate playlists, ask the user for a unique name
1121 #if self.playlist_name in self.playlists:
1123 #add hkp extension if necessary
1124 if not filename.endswith('.hkp'):
1125 filename = ''.join([filename, '.hkp'])
1126 #prefix with 'hookeDir' if just a filename or a relative path
1127 filename = lh.get_file_path(filename)
1128 if os.path.isfile(filename):
1129 #TODO: change cursor
1130 #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
1131 playlist_new = playlist.Playlist(self.drivers)
1132 playlist_new.load(filename)
1133 if playlist_new.count > 0:
1134 for curve in playlist_new.curves:
1135 plot = copy.deepcopy(curve.plots[0])
1136 for plotmanip in self.plotmanipulators:
1137 #to_plot = plotmanip[1](to_plot, curve)
1138 plot = plotmanip[1](plot, curve)
1139 curve.set_data('manipulated', plot.vectors[0][0], plot.vectors[0][1], color=plot.colors[0], style='plot')
1140 curve.add_data('manipulated', plot.vectors[1][0], plot.vectors[1][1], color=plot.colors[1], style='plot')
1141 self.AddToPlaylists(playlist_new)
1143 ##TODO: display dialog
1144 self.AppendToOutput(playlist_new.get_status_string())
1145 #TODO: change cursor
1146 #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
1148 #TODO: display dialog
1149 self.AppendToOutput(''.join['File ', filename, ' not found.\n'])
1152 def do_savelist(self, filename):
1155 Saves the current file playlist on disk.
1157 Syntax: savelist [filename]
1160 #self.playlist_generics['pointer'] = self._GetActiveCurveIndex
1161 pointer = self._GetActiveCurveIndex()
1162 #autocomplete filename if not specified
1163 if not filename.endswith('.hkp'):
1164 filename = filename.join(['.hkp'])
1166 playlist = self.GetActivePlaylist()
1168 playlist.save(filename)
1170 #PLOT INTERACTION COMMANDS
1171 #-------------------------------
1172 def UpdatePlot(self):
1174 if plot['visible'] and plot['x'] and plot['y']:
1175 color = plot['color']
1176 style = plot['style']
1178 axes.plot(plot['x'], plot['y'], color=color, zorder=1)
1179 if style == 'scatter':
1180 axes.scatter(plot['x'], plot['y'], color=color, s=0.5, zorder=2)
1182 def add_plot2(plot):
1183 if plot.visible and plot.x and plot.y:
1184 if plot.style == 'plot':
1185 axes.plot(plot.x, plot.y, color=plot.color, zorder=1)
1186 if plot.style == 'scatter':
1187 axes.scatter(plot.x, plot.y, color=plot.color, s=0.5, zorder=2)
1189 playlist_name = self._GetActivePlaylistName()
1190 index = self._GetActiveCurveIndex()
1191 playlist = self.playlists[playlist_name][0]
1192 curve = playlist.get_active_curve()
1193 plot = playlist.get_active_plot()
1194 figure = self.playlists[playlist_name][1]
1198 if curve.data.has_key('manipulated'):
1200 elif curve.data.has_key('raw'):
1201 exclude = 'manipulated'
1203 if exclude is not None:
1204 #TODO: what is this good for?
1205 if not hasattr(self, 'subplot'):
1206 axes = figure.add_subplot(111)
1208 axes.set_title(plot.title)
1209 axes.set_xlabel(plot.units[0])
1210 axes.set_ylabel(plot.units[1])
1212 for set_of_plots in curve.data:
1213 if set_of_plots != exclude:
1214 plots = curve.data[set_of_plots]
1215 for each_plot in plots:
1218 #TODO: add multiple results support
1219 #for fit in curve.fits:
1220 if curve.fits.has_key('wlc'):
1221 for plot in curve.fits['wlc'].results:
1223 self.panelResults.DisplayResults(curve.fits['wlc'])
1225 self.panelResults.ClearResults()
1227 axes.figure.canvas.draw()
1229 self.AppendToOutput('Not able to plot.')
1232 ID_PaneBorderSize = wx.ID_HIGHEST + 1
1233 ID_SashSize = ID_PaneBorderSize + 1
1234 ID_CaptionSize = ID_PaneBorderSize + 2
1235 ID_BackgroundColor = ID_PaneBorderSize + 3
1236 ID_SashColor = ID_PaneBorderSize + 4
1237 ID_InactiveCaptionColor = ID_PaneBorderSize + 5
1238 ID_InactiveCaptionGradientColor = ID_PaneBorderSize + 6
1239 ID_InactiveCaptionTextColor = ID_PaneBorderSize + 7
1240 ID_ActiveCaptionColor = ID_PaneBorderSize + 8
1241 ID_ActiveCaptionGradientColor = ID_PaneBorderSize + 9
1242 ID_ActiveCaptionTextColor = ID_PaneBorderSize + 10
1243 ID_BorderColor = ID_PaneBorderSize + 11
1244 ID_GripperColor = ID_PaneBorderSize + 12
1247 #----------------------------------------------------------------------
1249 if __name__ == '__main__':
1251 ## now, silence a deprecation warning for py2.3
1253 #warnings.filterwarnings("ignore", "integer", DeprecationWarning, "wxPython.gdi")
1258 app = Hooke(redirect=redirect)