4 Hooke - A force spectroscopy review & analysis tool.
9 import ConfigParser as configparser
11 import multiprocessing
13 from . import config as config_mod
14 from . import plugin as plugin_mod
15 from . import driver as driver_mod
25 #import libhooke as lh
30 #import hookepropertyeditor
35 def __init__(self, config=None, debug=0):
37 default_settings = (config_mod.DEFAULT_SETTINGS
38 + plugin_mod.default_settings()
39 + driver_mod.default_settings())
41 config = config_mod.HookeConfigParser(
42 paths=config_mod.DEFAULT_PATHS,
43 default_settings=default_settings)
49 def load_plugins(self):
51 for plugin_name,include in self.config.items('plugins'):
53 plugin = plugin_mod.PLUGINS[plugin_name]
56 self.config.items(plugin.setting_section))
57 except configparser.NoSectionError:
59 self.plugins.append(plugin_mod.PLUGINS[plugin_name])
61 def load_drivers(self):
63 for driver_name,include in self.config.items('drivers'):
65 driver = driver_mod.DRIVERS[driver_name]
68 self.config.items(driver.setting_section))
69 except configparser.NoSectionError:
71 self.drivers.append(driver_mod.DRIVERS[driver_name])
74 if self.config.changed:
75 self.config.write() # Does not preserve original comments
77 # #define the list of active drivers
79 # for driver in self.config['drivers']:
80 # if self.config['drivers'][driver]:
81 # #get the corresponding filename and path
82 # filename = ''.join([driver, '.py'])
83 # path = lh.get_file_path(filename, ['drivers'])
84 # #the driver is active for driver[1] == 1
85 # if os.path.isfile(path):
86 # #driver files are located in the 'drivers' subfolder
87 # driver_name = ''.join(['drivers.', driver])
88 # module = __import__(driver_name)
89 # class_file = getattr(drivers, driver)
90 # for command in dir(class_file):
91 # if command.endswith('Driver'):
92 # self.drivers.append(getattr(class_file, command))
93 # #import all active plugins and plotmanips
94 # #the plotmanip_functions contains: {the name of the plotmanip: [method, class_object]}
95 # plotmanip_functions = {}
96 # #add 'general.ini' to self.configs (this is not a plugin and thus must be imported seperately)
97 # ini_path = lh.get_file_path('general.ini', ['plugins'])
98 # plugin_config = ConfigObj(ini_path)
99 # #self.config.merge(plugin_config)
100 # self.configs['general'] = plugin_config
101 # #make sure we execute _plug_init() for every command line plugin we import
102 # for plugin in self.config['plugins']:
103 # if self.config['plugins'][plugin]:
104 # filename = ''.join([plugin, '.py'])
105 # path = lh.get_file_path(filename, ['plugins'])
106 # if os.path.isfile(path):
107 # #get the corresponding filename and path
108 # plugin_name = ''.join(['plugins.', plugin])
111 # module = __import__(plugin_name)
112 # #prepare the ini file for inclusion
113 # ini_path = path.replace('.py', '.ini')
115 # plugin_config = ConfigObj(ini_path)
116 # #self.config.merge(plugin_config)
117 # self.configs[plugin] = plugin_config
119 # commands = eval('dir(module.' + plugin+ '.' + plugin + 'Commands)')
120 # #keep only commands (ie names that start with 'do_')
121 # commands = [command for command in commands if command.startswith('do_')]
123 # self.plugins[plugin] = commands
125 # #initialize the plugin
126 # eval('module.' + plugin+ '.' + plugin + 'Commands._plug_init(self)')
127 # except AttributeError:
129 # except ImportError:
131 # #initialize the commands tree
132 # commands = dir(HookeFrame)
133 # commands = [command for command in commands if command.startswith('do_')]
135 # self.plugins['general'] = commands
136 # self.panelCommands.Initialize(self.plugins)
137 # for command in dir(self):
138 # if command.startswith('plotmanip_'):
139 # plotmanip_functions[command] = [command, getattr(self, command)]
140 # for name in self.config['plotmanipulators']['names']:
141 # if self.config['plotmanipulators'].as_bool(name):
142 # command_name = ''.join(['plotmanip_', name])
143 # if command_name in plotmanip_functions:
144 # self.plotmanipulators.append(plotmanip_functions[command_name])
145 # #load default list, if possible
146 # self.do_loadlist(self.config['general']['list'])
148 # def _BindEvents(self):
149 # self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
150 # self.Bind(wx.EVT_SIZE, self.OnSize)
151 # self.Bind(wx.EVT_CLOSE, self.OnClose)
152 # # Show How To Use The Closing Panes Event
153 # self.Bind(aui.EVT_AUI_PANE_CLOSE, self.OnPaneClose)
154 # self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnNotebookPageClose)
156 # self.Bind(wx.EVT_MENU, self.OnClose, id=wx.ID_EXIT)
157 # self.Bind(wx.EVT_MENU, self.OnAbout, id=wx.ID_ABOUT)
159 # self.Bind(wx.EVT_MENU_RANGE, self.OnView, id=ID_ViewAssistant, id2=ID_ViewResults)
161 # self.Bind(wx.EVT_MENU, self.OnDeletePerspective, id=ID_DeletePerspective)
162 # self.Bind(wx.EVT_MENU, self.OnSavePerspective, id=ID_SavePerspective)
163 # self.Bind(wx.EVT_MENU_RANGE, self.OnRestorePerspective, id=ID_FirstPerspective, id2=ID_FirstPerspective+1000)
165 # self.Bind(wx.EVT_TOOL, self.OnExportImage, id=ID_ExportImage)
166 # self.Bind(wx.EVT_TOOL, self.OnNext, id=ID_Next)
167 # self.Bind(wx.EVT_TOOL, self.OnPrevious, id=ID_Previous)
168 # #self.Bind(.EVT_AUITOOLBAR_TOOL_DROPDOWN, self.OnDropDownToolbarItem, id=ID_DropDownToolbarItem)
170 # treeCtrl = self.panelFolders.GetTreeCtrl()
171 # #tree.Bind(wx.EVT_LEFT_UP, self.OnDirCtrl1LeftUp)
172 # #tree.Bind(wx.EVT_LEFT_DOWN, self.OnGenericDirCtrl1LeftDown)
173 # treeCtrl.Bind(wx.EVT_LEFT_DCLICK, self.OnDirCtrlLeftDclick)
175 # self.panelPlaylists.PlaylistsTree.Bind(wx.EVT_LEFT_DOWN, self.OnPlaylistsLeftDown)
176 # self.panelPlaylists.PlaylistsTree.Bind(wx.EVT_LEFT_DCLICK, self.OnPlaylistsLeftDclick)
178 # self.panelCommands.ExecuteButton.Bind(wx.EVT_BUTTON, self.OnExecute)
179 # self.panelCommands.CommandsTree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeCtrlCommandsLeftDown)
181 # self.panelProperties.pg.Bind(wxpg.EVT_PG_CHANGED, self.OnPropGridChanged)
182 # self.panelProperties.pg.Bind(wxpg.EVT_PG_SELECTED, self.OnPropGridSelect)
184 # self.panelResults.results_list.OnCheckItem = self.OnResultsCheck
186 # def _GetActiveCurveIndex(self):
187 # playlist = self.GetActivePlaylist()
188 # #get the selected item from the tree
189 # selected_item = self.panelPlaylists.PlaylistsTree.GetSelection()
190 # #test if a playlist or a curve was double-clicked
191 # if self.panelPlaylists.PlaylistsTree.ItemHasChildren(selected_item):
195 # selected_item = self.panelPlaylists.PlaylistsTree.GetPrevSibling(selected_item)
196 # while selected_item.IsOk():
198 # selected_item = self.panelPlaylists.PlaylistsTree.GetPrevSibling(selected_item)
201 # def _GetActivePlaylistName(self):
202 # #get the selected item from the tree
203 # selected_item = self.panelPlaylists.PlaylistsTree.GetSelection()
204 # #test if a playlist or a curve was double-clicked
205 # if self.panelPlaylists.PlaylistsTree.ItemHasChildren(selected_item):
206 # playlist_item = selected_item
208 # #get the name of the playlist
209 # playlist_item = self.panelPlaylists.PlaylistsTree.GetItemParent(selected_item)
210 # #now we have a playlist
211 # return self.panelPlaylists.PlaylistsTree.GetItemText(playlist_item)
213 # def _GetPlaylistTab(self, name):
214 # for index, page in enumerate(self.plotNotebook._tabs._pages):
215 # if page.caption == name:
219 # def _GetUniquePlaylistName(self, name):
220 # playlist_name = name
222 # while playlist_name in self.playlists:
223 # playlist_name = ''.join([name, str(count)])
225 # return playlist_name
227 # def _SavePerspectiveToFile(self, name, perspective):
228 # filename = ''.join([name, '.txt'])
229 # filename = lh.get_file_path(filename, ['perspectives'])
230 # perspectivesFile = open(filename, 'w')
231 # perspectivesFile.write(perspective)
232 # perspectivesFile.close()
234 # def AddPlaylist(self, playlist=None, name='Untitled'):
235 # #TODO: change cursor or progressbar (maybe in statusbar)
236 # #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
237 # if playlist and playlist.count > 0:
238 # playlist.name = self._GetUniquePlaylistName(name)
240 # self.AddToPlaylists(playlist)
242 # def AddPlaylistFromFiles(self, files=[], name='Untitled'):
243 # #TODO: change cursor or progressbar (maybe in statusbar)
244 # #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
246 # playlist = Playlist.Playlist(self.drivers)
248 # playlist.add_curve(item)
249 # if playlist.count > 0:
250 # playlist.name = self._GetUniquePlaylistName(name)
252 # self.AddToPlaylists(playlist)
254 # def AddToPlaylists(self, playlist):
255 # if playlist.has_curves:
256 # #setup the playlist in the Playlist tree
257 # tree_root = self.panelPlaylists.PlaylistsTree.GetRootItem()
258 # playlist_root = self.panelPlaylists.PlaylistsTree.AppendItem(tree_root, playlist.name, 0)
259 # #add all curves to the Playlist tree
261 # for index, curve in enumerate(playlist.curves):
262 # ##remove the extension from the name of the curve
264 # #item_text, extension = os.path.splitext(curve.name)
265 # #curve_ID = self.panelPlaylists.PlaylistsTree.AppendItem(playlist_root, item_text, 1)
266 # curve_ID = self.panelPlaylists.PlaylistsTree.AppendItem(playlist_root, curve.name, 1)
267 # if index == playlist.index:
268 # self.panelPlaylists.PlaylistsTree.SelectItem(curve_ID)
270 # #create the plot tab and add playlist to the dictionary
271 # plotPanel = wxmpl.PlotPanel(self, ID_FirstPlot + len(self.playlists))
272 # notebook_tab = self.plotNotebook.AddPage(plotPanel, playlist.name, True)
273 # tab_index = self.plotNotebook.GetSelection()
274 # figure = plotPanel.get_figure()
275 # self.playlists[playlist.name] = [playlist, figure]
276 # self.panelPlaylists.PlaylistsTree.Expand(playlist_root)
277 # self.statusbar.SetStatusText(playlist.get_status_string(), 0)
280 # def AppendToOutput(self, text):
281 # self.panelOutput.AppendText(''.join([text, '\n']))
283 # def CreateApplicationIcon(self):
284 # iconFile = 'resources' + os.sep + 'microscope.ico'
285 # icon = wx.Icon(iconFile, wx.BITMAP_TYPE_ICO)
288 # def CreateCommandLine(self):
289 # return wx.TextCtrl(self, -1, '', style=wx.NO_BORDER|wx.EXPAND)
291 # def CreatePanelAssistant(self):
292 # panel = wx.TextCtrl(self, -1, '', wx.Point(0, 0), wx.Size(150, 90), wx.NO_BORDER|wx.TE_MULTILINE)
293 # panel.SetEditable(False)
296 # def CreatePanelCommands(self):
297 # return hookecommands.Commands(self)
299 # def CreatePanelFolders(self):
301 # filters = self.config['folders']['filters']
302 # index = self.config['folders'].as_int('filterindex')
303 # #set initial directory
304 # folder = self.config['general']['workdir']
305 # return wx.GenericDirCtrl(self, -1, dir=folder, size=(200, 250), style=wx.DIRCTRL_SHOW_FILTERS, filter=filters, defaultFilter=index)
307 # def CreatePanelOutput(self):
308 # return wx.TextCtrl(self, -1, '', wx.Point(0, 0), wx.Size(150, 90), wx.NO_BORDER|wx.TE_MULTILINE)
310 # def CreatePanelPlaylists(self):
311 # return hookeplaylist.Playlists(self)
313 # def CreatePanelProperties(self):
314 # return hookepropertyeditor.PropertyEditor(self)
316 # def CreatePanelResults(self):
317 # return hookeresults.Results(self)
319 # def CreatePanelWelcome(self):
320 # ctrl = wx.html.HtmlWindow(self, -1, wx.DefaultPosition, wx.Size(400, 300))
321 # introStr = '<h1>Welcome to Hooke</h1>' + \
322 # '<h3>Features</h3>' + \
324 # '<li>View, annotate, measure force curves</li>' + \
325 # '<li>Worm-like chain fit of force peaks</li>' + \
326 # '<li>Automatic convolution-based filtering of empty curves</li>' + \
327 # '<li>Automatic fit and measurement of multiple force peaks</li>' + \
328 # '<li>Handles force-clamp force experiments (experimental)</li>' + \
329 # '<li>It is extensible by users by means of plugins and drivers</li>' + \
331 # '<p>See the <a href="/p/hooke/wiki/DocumentationIndex">DocumentationIndex</a> for more information</p>'
332 # ctrl.SetPage(introStr)
335 # def CreateMenuBar(self):
336 # menu_bar = wx.MenuBar()
338 # file_menu = wx.Menu()
339 # file_menu.Append(wx.ID_OPEN, '&Open playlist\tCtrl-O')
340 # file_menu.Append(wx.ID_SAVE, 'Save playlist\tCtrl-S')
341 # file_menu.AppendSeparator()
342 # file_menu.Append(wx.ID_EXIT, 'Exit\tCtrl-Q')
344 # edit_menu = wx.Menu()
345 # edit_menu.Append(ID_ExportText, 'Export text...')
346 # edit_menu.Append(ID_ExportImage, 'Export image...')
347 # edit_menu.AppendSeparator();
348 # edit_menu.Append(ID_Config, 'Preferences')
350 # view_menu = wx.Menu()
351 # view_menu.AppendCheckItem(ID_ViewFolders, 'Folders\tF5')
352 # view_menu.AppendCheckItem(ID_ViewPlaylists, 'Playlists\tF6')
353 # view_menu.AppendCheckItem(ID_ViewCommands, 'Commands\tF7')
354 # view_menu.AppendCheckItem(ID_ViewProperties, 'Properties\tF8')
355 # view_menu.AppendCheckItem(ID_ViewAssistant, 'Assistant\tF9')
356 # view_menu.AppendCheckItem(ID_ViewResults, 'Results\tF10')
357 # view_menu.AppendCheckItem(ID_ViewOutput, 'Output\tF11')
359 # self._perspectives_menu = self.CreatePerspectivesMenu()
361 # help_menu = wx.Menu()
362 # help_menu.Append(wx.ID_ABOUT, 'About Hooke')
363 # #put it all together
364 # menu_bar.Append(file_menu, 'File')
365 # menu_bar.Append(edit_menu, 'Edit')
366 # menu_bar.Append(view_menu, 'View')
367 # menu_bar.Append(self._perspectives_menu, "Perspectives")
368 # menu_bar.Append(help_menu, 'Help')
370 # self.SetMenuBar(menu_bar)
372 # def CreateNotebook(self):
373 # # create the notebook off-window to avoid flicker
374 # client_size = self.GetClientSize()
375 # ctrl = aui.AuiNotebook(self, -1, wx.Point(client_size.x, client_size.y), wx.Size(430, 200), self._notebook_style)
376 # arts = [aui.AuiDefaultTabArt, aui.AuiSimpleTabArt, aui.VC71TabArt, aui.FF2TabArt, aui.VC8TabArt, aui.ChromeTabArt]
377 # art = arts[self._notebook_theme]()
378 # ctrl.SetArtProvider(art)
379 # #uncomment if we find a nice icon
380 # #page_bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, wx.Size(16, 16))
381 # ctrl.AddPage(self.CreatePanelWelcome(), "Welcome", False)
384 # def CreatePerspectivesMenu(self):
386 # menu.Append(ID_SavePerspective, "Save Perspective")
387 # menu.Append(ID_DeletePerspective, "Delete Perspective")
388 # menu.AppendSeparator()
389 # #add perspectives to menubar and _perspectives
390 # perspectivesDirectory = os.path.join(lh.hookeDir, 'perspectives')
391 # if os.path.isdir(perspectivesDirectory):
392 # perspectiveFileNames = os.listdir(perspectivesDirectory)
393 # for perspectiveFilename in perspectiveFileNames:
394 # filename = lh.get_file_path(perspectiveFilename, ['perspectives'])
395 # if os.path.isfile(filename):
396 # perspectiveFile = open(filename, 'rU')
397 # perspective = perspectiveFile.readline()
398 # perspectiveFile.close()
399 # if perspective != '':
400 # name, extension = os.path.splitext(perspectiveFilename)
401 # if extension == '.txt':
402 # menuItem = menu.AppendRadioItem(ID_FirstPerspective + len(self._perspectives), name)
403 # self._perspectives[name] = [len(self._perspectives), perspective]
404 # if self.config['perspectives']['active'] == name:
406 # #in case there are no perspectives
407 # if not self._perspectives:
408 # perspective = self._mgr.SavePerspective()
409 # self.config['perspectives']['default'] = 'Default'
410 # self._perspectives['Default'] = [0, perspective]
411 # menuItem = menu.AppendRadioItem(ID_FirstPerspective, 'Default')
413 # self._SavePerspectiveToFile('Default', perspective)
416 # def CreateStatusbar(self):
417 # statusbar = self.CreateStatusBar(2, wx.ST_SIZEGRIP)
418 # statusbar.SetStatusWidths([-2, -3])
419 # statusbar.SetStatusText('Ready', 0)
420 # welcomeString=u'Welcome to Hooke (version '+__version__+', '+__release_name__+')!'
421 # statusbar.SetStatusText(welcomeString, 1)
424 # def CreateToolBar(self):
425 # toolbar = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_FLAT | wx.TB_NODIVIDER)
426 # toolbar.SetToolBitmapSize(wx.Size(16,16))
427 # toolbar_bmp1 = wx.ArtProvider_GetBitmap(wx.ART_QUESTION, wx.ART_OTHER, wx.Size(16, 16))
428 # toolbar_bmpOpen = wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, wx.Size(16, 16))
429 # toolbar_bmpSave = wx.ArtProvider_GetBitmap(wx.ART_FILE_SAVE, wx.ART_OTHER, wx.Size(16, 16))
430 # toolbar_bmpExportText = wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, wx.Size(16, 16))
431 # toolbar_bmpExportImage = wx.ArtProvider_GetBitmap(wx.ART_MISSING_IMAGE, wx.ART_OTHER, wx.Size(16, 16))
432 # toolbar.AddLabelTool(101, 'Open', toolbar_bmpOpen)
433 # toolbar.AddLabelTool(102, 'Save', toolbar_bmpSave)
434 # toolbar.AddSeparator()
435 # toolbar.AddLabelTool(ID_ExportText, 'Export text...', toolbar_bmpExportText)
436 # toolbar.AddLabelTool(ID_ExportImage, 'Export image...', toolbar_bmpExportImage)
440 # def CreateToolBarNavigation(self):
441 # toolbar = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_FLAT | wx.TB_NODIVIDER)
442 # toolbar.SetToolBitmapSize(wx.Size(16,16))
443 # toolbar_bmpBack = wx.ArtProvider_GetBitmap(wx.ART_GO_BACK, wx.ART_OTHER, wx.Size(16, 16))
444 # toolbar_bmpForward = wx.ArtProvider_GetBitmap(wx.ART_GO_FORWARD, wx.ART_OTHER, wx.Size(16, 16))
445 # toolbar.AddLabelTool(ID_Previous, 'Previous', toolbar_bmpBack, shortHelp='Previous curve')
446 # toolbar.AddLabelTool(ID_Next, 'Next', toolbar_bmpForward, shortHelp='Next curve')
450 # def DeleteFromPlaylists(self, name):
451 # if name in self.playlists:
452 # del self.playlists[name]
453 # tree_root = self.panelPlaylists.PlaylistsTree.GetRootItem()
454 # item, cookie = self.panelPlaylists.PlaylistsTree.GetFirstChild(tree_root)
456 # playlist_name = self.panelPlaylists.PlaylistsTree.GetItemText(item)
457 # if playlist_name == name:
459 # self.panelPlaylists.PlaylistsTree.Delete(item)
462 # item = self.panelPlaylists.PlaylistsTree.GetNextSibling(item)
463 # self.OnPlaylistsLeftDclick(None)
465 # def DeletePlotPage(self, name):
466 # index = self._GetPlaylistTab(name)
467 # plot = self.playlists[name][1]
469 # self.plotNotebook.RemovePage(index)
470 # self.DeleteFromPlaylists(name)
472 # def GetActiveCurve(self):
473 # playlist = self.GetActivePlaylist()
474 # if playlist is not None:
475 # return playlist.get_active_curve()
478 # def GetActivePlaylist(self):
479 # playlist_name = self._GetActivePlaylistName()
480 # if playlist_name in self.playlists:
481 # return self.playlists[playlist_name][0]
484 # def GetActivePlot(self):
485 # curve = self.GetActiveCurve()
486 # if curve is not None:
487 # return curve.plots[0]
490 # def GetDockArt(self):
491 # return self._mgr.GetArtProvider()
493 # def GetBoolFromConfig(self, *args):
498 # elif len(args) == 3:
502 # if self.configs.has_key(plugin):
503 # config = self.configs[plugin]
504 # return config[section][key].as_bool('value')
507 # def GetFloatFromConfig(self, *args):
512 # elif len(args) == 3:
516 # if self.configs.has_key(plugin):
517 # config = self.configs[plugin]
518 # return config[section][key].as_float('value')
521 # def GetIntFromConfig(self, *args):
526 # elif len(args) == 3:
530 # if self.configs.has_key(plugin):
531 # config = self.configs[plugin]
532 # return config[section][key].as_int('value')
535 # def GetStringFromConfig(self, *args):
540 # elif len(args) == 3:
544 # if self.configs.has_key(plugin):
545 # config = self.configs[plugin]
546 # return config[section][key]['value']
549 # def GetPerspectiveMenuItem(self, name):
550 # index = self._perspectives[name][0]
551 # perspective_Id = ID_FirstPerspective + index
552 # menu_item = self.MenuBar.FindItemById(perspective_Id)
555 # def HasPlotmanipulator(self, name):
557 # returns True if the plotmanipulator 'name' is loaded, False otherwise
559 # for plotmanipulator in self.plotmanipulators:
560 # if plotmanipulator[0] == name:
564 # def OnAbout(self, event):
565 # msg = 'Hooke\n\n'+\
566 # 'A free, open source data analysis platform\n'+\
567 # '(c) 2006-2008 Massimo Sandal\n\n'+\
568 # '(c) 2009 Dr. Rolf Schmidt\n\n'+\
569 # 'Released under the GNU GPL v2'
570 # dialog = wx.MessageDialog(self, msg, "About Hooke", wx.OK | wx.ICON_INFORMATION)
574 # def OnClose(self, event):
576 # self.config['main']['height'] = str(self.GetSize().GetHeight())
577 # self.config['main']['left'] = str(self.GetPosition()[0])
578 # self.config['main']['top'] = str(self.GetPosition()[1])
579 # self.config['main']['width'] = str(self.GetSize().GetWidth())
580 # # Writing the configuration file to 'hooke.ini'
581 # self.config.write()
586 # def OnDeletePerspective(self, event):
589 # def OnDirCtrlLeftDclick(self, event):
590 # file_path = self.panelFolders.GetPath()
591 # if os.path.isfile(file_path):
592 # if file_path.endswith('.hkp'):
593 # self.do_loadlist(file_path)
598 # def OnEraseBackground(self, event):
601 # def OnExecute(self, event):
602 # item = self.panelCommands.CommandsTree.GetSelection()
604 # if self.panelCommands.CommandsTree.ItemHasChildren(item):
608 # parent = self.panelCommands.CommandsTree.GetItemParent(item)
609 # if not self.panelCommands.CommandsTree.ItemHasChildren(item):
610 # parent_text = self.panelCommands.CommandsTree.GetItemText(parent)
611 # item_text = self.panelCommands.CommandsTree.GetItemText(item)
612 # if item_text in ['genlist', 'loadlist', 'savelist']:
613 # property_values = self.panelProperties.GetPropertyValues()
615 # for item in property_values:
616 # arg_str = ''.join([arg_str, item, '=r"', str(property_values[item]), '", '])
617 # command = ''.join(['self.do_', item_text, '(', arg_str, ')'])
619 # command = ''.join(['self.do_', item_text, '()'])
623 # def OnExit(self, event):
626 # def OnExportImage(self, event):
629 # def OnNext(self, event):
632 # Go to the next curve in the playlist.
633 # If we are at the last curve, we come back to the first.
637 # selected_item = self.panelPlaylists.PlaylistsTree.GetSelection()
638 # if self.panelPlaylists.PlaylistsTree.ItemHasChildren(selected_item):
639 # #GetFirstChild returns a tuple
640 # #we only need the first element
641 # next_item = self.panelPlaylists.PlaylistsTree.GetFirstChild(selected_item)[0]
643 # next_item = self.panelPlaylists.PlaylistsTree.GetNextSibling(selected_item)
644 # if not next_item.IsOk():
645 # parent_item = self.panelPlaylists.PlaylistsTree.GetItemParent(selected_item)
646 # #GetFirstChild returns a tuple
647 # #we only need the first element
648 # next_item = self.panelPlaylists.PlaylistsTree.GetFirstChild(parent_item)[0]
649 # self.panelPlaylists.PlaylistsTree.SelectItem(next_item, True)
650 # playlist = self.playlists[self._GetActivePlaylistName()][0]
651 # if playlist.count > 1:
653 # self.statusbar.SetStatusText(playlist.get_status_string(), 0)
656 # def OnNotebookPageClose(self, event):
657 # ctrl = event.GetEventObject()
658 # playlist_name = ctrl.GetPageText(ctrl._curpage)
659 # self.DeleteFromPlaylists(playlist_name)
661 # def OnPaneClose(self, event):
664 # def OnPlaylistsLeftDclick(self, event):
665 # playlist_name = self._GetActivePlaylistName()
666 # #if that playlist already exists
667 # #we check if it is the active playlist (ie selected in panelPlaylists)
668 # #and switch to it if necessary
669 # if playlist_name in self.playlists:
670 # index = self.plotNotebook.GetSelection()
671 # current_playlist = self.plotNotebook.GetPageText(index)
672 # #new_playlist = self.playlists[playlist_name][0]
673 # #if current_playlist != new_playlist:
674 # if current_playlist != playlist_name:
675 # index = self._GetPlaylistTab(playlist_name)
676 # self.plotNotebook.SetSelection(index)
677 # #if a curve was double-clicked
678 # item = self.panelPlaylists.PlaylistsTree.GetSelection()
679 # #TODO: fix with get_active_curve
680 # if not self.panelPlaylists.PlaylistsTree.ItemHasChildren(item):
681 # index = self._GetActiveCurveIndex()
685 # playlist = self.playlists[playlist_name][0]
686 # playlist.index = index
687 # self.statusbar.SetStatusText(playlist.get_status_string(), 0)
689 # #if you uncomment the following line, the tree will collapse/expand as well
692 # def OnPlaylistsLeftDown(self, event):
693 # hit_item, hit_flags = self.panelPlaylists.PlaylistsTree.HitTest(event.GetPosition())
694 # if (hit_flags & wx.TREE_HITTEST_ONITEM) != 0:
696 # self.panelPlaylists.PlaylistsTree.SelectItem(hit_item)
697 # playlist_name = self._GetActivePlaylistName()
698 # playlist = self.playlists[playlist_name][0]
699 # #if a curve was clicked
700 # item = self.panelPlaylists.PlaylistsTree.GetSelection()
701 # if not self.panelPlaylists.PlaylistsTree.ItemHasChildren(item):
702 # #TODO: fix with get_active_curve
703 # index = self._GetActiveCurveIndex()
705 # #playlist = self.playlists[playlist_name][0]
706 # playlist.index = index
707 # #self.playlists[playlist_name][0].index = index
709 # ##self.playlists[playlist_name][0].index = 0
710 # #playlist.index = index
711 # self.playlists[playlist_name][0] = playlist
714 # def OnPrevious(self, event):
717 # Go to the previous curve in the playlist.
718 # If we are at the first curve, we jump to the last.
720 # Syntax: previous, p
722 # #playlist = self.playlists[self._GetActivePlaylistName()][0]
723 # #select the previous curve and tell the user if we wrapped around
724 # #self.AppendToOutput(playlist.previous())
725 # selected_item = self.panelPlaylists.PlaylistsTree.GetSelection()
726 # if self.panelPlaylists.PlaylistsTree.ItemHasChildren(selected_item):
727 # previous_item = self.panelPlaylists.PlaylistsTree.GetLastChild(selected_item)
729 # previous_item = self.panelPlaylists.PlaylistsTree.GetPrevSibling(selected_item)
730 # if not previous_item.IsOk():
731 # parent_item = self.panelPlaylists.PlaylistsTree.GetItemParent(selected_item)
732 # previous_item = self.panelPlaylists.PlaylistsTree.GetLastChild(parent_item)
733 # self.panelPlaylists.PlaylistsTree.SelectItem(previous_item, True)
734 # playlist = self.playlists[self._GetActivePlaylistName()][0]
735 # if playlist.count > 1:
736 # playlist.previous()
737 # self.statusbar.SetStatusText(playlist.get_status_string(), 0)
740 # def OnPropGridChanged (self, event):
741 # prop = event.GetProperty()
743 # item_section = self.panelProperties.SelectedTreeItem
744 # item_plugin = self.panelCommands.CommandsTree.GetItemParent(item_section)
745 # plugin = self.panelCommands.CommandsTree.GetItemText(item_plugin)
746 # config = self.configs[plugin]
747 # property_section = self.panelCommands.CommandsTree.GetItemText(item_section)
748 # property_key = prop.GetName()
749 # property_value = prop.GetValue()
750 # config[property_section][property_key]['value'] = property_value
752 # def OnPropGridSelect(self, event):
755 # def OnRestorePerspective(self, event):
756 # name = self.MenuBar.FindItemById(event.GetId()).GetLabel()
757 # self._mgr.LoadPerspective(self._perspectives[name][1])
758 # self.config['perspectives']['active'] = name
760 # all_panes = self._mgr.GetAllPanes()
761 # for pane in all_panes:
762 # if not pane.name.startswith('toolbar'):
763 # if pane.name == 'Assistant':
764 # self.MenuBar.FindItemById(ID_ViewAssistant).Check(pane.window.IsShown())
765 # if pane.name == 'Folders':
766 # self.MenuBar.FindItemById(ID_ViewFolders).Check(pane.window.IsShown())
767 # if pane.name == 'Playlists':
768 # self.MenuBar.FindItemById(ID_ViewPlaylists).Check(pane.window.IsShown())
769 # if pane.name == 'Commands':
770 # self.MenuBar.FindItemById(ID_ViewCommands).Check(pane.window.IsShown())
771 # if pane.name == 'Properties':
772 # self.MenuBar.FindItemById(ID_ViewProperties).Check(pane.window.IsShown())
773 # if pane.name == 'Output':
774 # self.MenuBar.FindItemById(ID_ViewOutput).Check(pane.window.IsShown())
775 # if pane.name == 'Results':
776 # self.MenuBar.FindItemById(ID_ViewResults).Check(pane.window.IsShown())
778 # def OnResultsCheck(self, index, flag):
779 # curve = self.GetActiveCurve()
780 # result = curve.data['results'][index]['visible'] = flag
783 # def OnSavePerspective(self, event):
784 # def nameExists(name):
785 # for item in self._perspectives_menu.GetMenuItems():
786 # if item.GetText() == name:
792 # dialog = wx.TextEntryDialog(self, 'Enter a name for the new perspective:', 'Save perspective')
793 # dialog.SetValue('New perspective')
794 # if dialog.ShowModal() != wx.ID_OK:
797 # name = dialog.GetValue()
799 # if nameExists(name):
800 # 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)
801 # if dialogConfirm.ShowModal() == wx.ID_YES:
806 # perspective = self._mgr.SavePerspective()
808 # if nameExists(name):
809 # #check the corresponding menu item
810 # menuItem = self.GetPerspectiveMenuItem(name)
811 # #replace the perspectiveStr in _pespectives
812 # index = self._perspectives[name][0]
813 # self._perspectives[name] = [index, perspective]
815 # #simply add the new perspective to _perspectives
816 # index = len(self._perspectives)
817 # self._perspectives[name] = [len(self._perspectives), perspective]
818 # menuItem = self._perspectives_menu.AppendRadioItem(ID_FirstPerspective + len(self._perspectives), name)
821 # self._SavePerspectiveToFile(name, perspective)
822 # #uncheck all perspective menu items
823 # #as these are radio items, one item has to be checked at all times
824 # #the line 'menuItem.Check()' above actually checks a second item
825 # #but does not toggle
826 # #so we need to uncheck all other items afterwards
827 # #weirdly enough, menuitem.Toggle() doesn't do this properly either
828 # for item in self._perspectives_menu.GetMenuItems():
829 # if item.IsCheckable():
830 # if item.GetLabel() != name:
833 # def OnView(self, event):
834 # menu_id = event.GetId()
835 # menu_item = self.MenuBar.FindItemById(menu_id)
836 # menu_label = menu_item.GetLabel()
838 # pane = self._mgr.GetPane(menu_label)
839 # pane.Show(not pane.IsShown())
840 # #if we don't do the following, the Folders pane does not resize properly on hide/show
841 # if pane.caption == 'Folders' and pane.IsShown() and pane.IsDocked():
842 # #folders_size = pane.GetSize()
843 # self.panelFolders.Fit()
846 # def OnSize(self, event):
849 # def OnTreeCtrlCommandsLeftDown(self, event):
850 # hit_item, hit_flags = self.panelCommands.CommandsTree.HitTest(event.GetPosition())
851 # if (hit_flags & wx.TREE_HITTEST_ONITEM) != 0:
852 # self.panelCommands.CommandsTree.SelectItem(hit_item)
853 # self.panelProperties.SelectedTreeItem = hit_item
854 # #if a command was clicked
856 # if not self.panelCommands.CommandsTree.ItemHasChildren(hit_item):
857 # item_plugin = self.panelCommands.CommandsTree.GetItemParent(hit_item)
858 # plugin = self.panelCommands.CommandsTree.GetItemText(item_plugin)
859 # if self.configs.has_key(plugin):
860 # #config = self.panelCommands.CommandsTree.GetPyData(item_plugin)
861 # config = self.configs[plugin]
862 # section = self.panelCommands.CommandsTree.GetItemText(hit_item)
863 # #display docstring in help window
864 # doc_string = eval('self.do_' + section + '.__doc__')
865 # if section in config:
866 # for option in config[section]:
867 # properties.append([option, config[section][option]])
869 # module = self.panelCommands.CommandsTree.GetItemText(hit_item)
870 # if module != 'general':
871 # doc_string = eval('plugins.' + module + '.' + module + 'Commands.__doc__')
873 # doc_string = 'The module "general" contains Hooke core functionality'
874 # if doc_string is not None:
875 # self.panelAssistant.ChangeValue(doc_string)
876 # hookepropertyeditor.PropertyEditor.Initialize(self.panelProperties, properties)
879 # def UpdatePlaylists(self):
880 # #setup the playlist in the Playlist tree
881 # tree_root = self.panelPlaylists.PlaylistsTree.GetRootItem()
882 # playlist_root = self.panelPlaylists.PlaylistsTree.AppendItem(tree_root, playlist.name, 0)
883 # #add all curves to the Playlist tree
885 # for index, curve in enumerate(playlist.curves):
886 # ##remove the extension from the name of the curve
888 # #item_text, extension = os.path.splitext(curve.name)
889 # #curve_ID = self.panelPlaylists.PlaylistsTree.AppendItem(playlist_root, item_text, 1)
890 # curve_ID = self.panelPlaylists.PlaylistsTree.AppendItem(playlist_root, curve.name, 1)
891 # if index == playlist.index:
892 # self.panelPlaylists.PlaylistsTree.SelectItem(curve_ID)
893 # #create the plot tab and add playlist to the dictionary
894 # plotPanel = wxmpl.PlotPanel(self, ID_FirstPlot + len(self.playlists))
895 # notebook_tab = self.plotNotebook.AddPage(plotPanel, playlist.name, True)
896 # #tab_index = self.plotNotebook.GetSelection()
897 # figure = plotPanel.get_figure()
898 # #self.playlists[playlist.name] = [playlist, tab_index, figure]
899 # self.playlists[playlist.name] = [playlist, figure]
900 # self.panelPlaylists.PlaylistsTree.Expand(playlist_root)
901 # self.statusbar.SetStatusText(playlist.get_status_string(), 0)
905 ##Everything sending an event should be here
906 # def _measure_N_points(self, N, whatset=1):
908 # general helper function for N-points measures
910 # wx.PostEvent(self.frame,self.list_of_events['measure_points'](num_of_points=N, set=whatset))
913 # points=self.frame.events_from_gui.get()
919 # def _clickize(self, xvector, yvector, index):
921 # returns a ClickedPoint() object from an index and vectors of x, y coordinates
923 # point = lh.ClickedPoint()
924 # point.index = index
925 # point.absolute_coords = xvector[index], yvector[index]
926 # point.find_graph_coords(xvector, yvector)
929 ##PLAYLIST INTERACTION COMMANDS
930 ##-------------------------------
931 # def do_genlist(self, folder=lh.hookeDir, filemask='*.*'):
934 # Generates a file playlist.
935 # Note it doesn't *save* it: see savelist for this.
937 # If [input files] is a directory, it will use all files in the directory for playlist.
943 # are all equivalent syntax.
945 # Syntax: genlist [input files]
947 # #args list is: input folder, file mask
948 # if os.path.isdir(folder):
949 # path = os.path.join(folder, filemask)
950 # #expanding correctly the input list with the glob module :)
951 # files = glob.glob(path)
953 # #TODO: change cursor or progressbar (maybe in statusbar)
954 # #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
955 # playlist = playlist.Playlist(self.drivers)
957 # curve = playlist.add_curve(item)
958 # plot = copy.deepcopy(curve.plots[0])
959 # #add the 'raw' data
960 # curve.add_data('raw', plot.vectors[0][0], plot.vectors[0][1], color=plot.colors[0], style='plot')
961 # curve.add_data('raw', plot.vectors[1][0], plot.vectors[1][1], color=plot.colors[1], style='plot')
962 # #apply all active plotmanipulators and add the 'manipulated' data
963 # for plotmanipulator in self.plotmanipulators:
964 # plot = plotmanipulator[1](plot, curve)
965 # curve.set_data('manipulated', plot.vectors[0][0], plot.vectors[0][1], color=plot.colors[0], style='plot')
966 # curve.add_data('manipulated', plot.vectors[1][0], plot.vectors[1][1], color=plot.colors[1], style='plot')
967 # if playlist.count > 0:
968 # playlist.name = self._GetUniquePlaylistName(os.path.basename(folder))
970 # self.AddToPlaylists(playlist)
971 # self.AppendToOutput(playlist.get_status_string())
973 # self.AppendToOutput(''.join(['Cannot find folder ', folder]))
975 # def do_loadlist(self, filename):
978 # Loads a file playlist
980 # Syntax: loadlist [playlist file]
982 # #TODO: check for duplicate playlists, ask the user for a unique name
983 # #if self.playlist_name in self.playlists:
985 # #add hkp extension if necessary
986 # if not filename.endswith('.hkp'):
987 # filename = ''.join([filename, '.hkp'])
988 # #prefix with 'hookeDir' if just a filename or a relative path
989 # filename = lh.get_file_path(filename)
990 # if os.path.isfile(filename):
991 # #TODO: change cursor
992 # #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
993 # playlist_new = playlist.Playlist(self.drivers)
994 # playlist_new.load(filename)
995 # if playlist_new.count > 0:
996 # for curve in playlist_new.curves:
997 # plot = copy.deepcopy(curve.plots[0])
998 # for plotmanip in self.plotmanipulators:
999 # #to_plot = plotmanip[1](to_plot, curve)
1000 # plot = plotmanip[1](plot, curve)
1001 # curve.set_data('manipulated', plot.vectors[0][0], plot.vectors[0][1], color=plot.colors[0], style='plot')
1002 # curve.add_data('manipulated', plot.vectors[1][0], plot.vectors[1][1], color=plot.colors[1], style='plot')
1003 # self.AddToPlaylists(playlist_new)
1005 # ##TODO: display dialog
1006 # self.AppendToOutput(playlist_new.get_status_string())
1007 # #TODO: change cursor
1008 # #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
1010 # #TODO: display dialog
1011 # self.AppendToOutput(''.join['File ', filename, ' not found.\n'])
1014 # def do_savelist(self, filename):
1017 # Saves the current file playlist on disk.
1019 # Syntax: savelist [filename]
1022 # #self.playlist_generics['pointer'] = self._GetActiveCurveIndex
1023 # pointer = self._GetActiveCurveIndex()
1024 # #autocomplete filename if not specified
1025 # if not filename.endswith('.hkp'):
1026 # filename = filename.join(['.hkp'])
1028 # playlist = self.GetActivePlaylist()
1029 # playlist.set_XML()
1030 # playlist.save(filename)
1032 ##PLOT INTERACTION COMMANDS
1033 ##-------------------------------
1034 # def UpdatePlot(self):
1035 # def add_plot(plot):
1036 # if plot['visible'] and plot['x'] and plot['y']:
1037 # color = plot['color']
1038 # style = plot['style']
1039 # if style == 'plot':
1040 # axes.plot(plot['x'], plot['y'], color=color, zorder=1)
1041 # if style == 'scatter':
1042 # axes.scatter(plot['x'], plot['y'], color=color, s=0.5, zorder=2)
1044 # def add_plot2(plot):
1045 # if plot.visible and plot.x and plot.y:
1046 # if plot.style == 'plot':
1047 # axes.plot(plot.x, plot.y, color=plot.color, zorder=1)
1048 # if plot.style == 'scatter':
1049 # axes.scatter(plot.x, plot.y, color=plot.color, s=0.5, zorder=2)
1051 # playlist_name = self._GetActivePlaylistName()
1052 # index = self._GetActiveCurveIndex()
1053 # playlist = self.playlists[playlist_name][0]
1054 # curve = playlist.get_active_curve()
1055 # plot = playlist.get_active_plot()
1056 # figure = self.playlists[playlist_name][1]
1060 # if curve.data.has_key('manipulated'):
1062 # elif curve.data.has_key('raw'):
1063 # exclude = 'manipulated'
1065 # if exclude is not None:
1066 # #TODO: what is this good for?
1067 # if not hasattr(self, 'subplot'):
1068 # axes = figure.add_subplot(111)
1070 # axes.set_title(plot.title)
1071 # axes.set_xlabel(plot.units[0])
1072 # axes.set_ylabel(plot.units[1])
1074 # for set_of_plots in curve.data:
1075 # if set_of_plots != exclude:
1076 # plots = curve.data[set_of_plots]
1077 # for each_plot in plots:
1078 # add_plot(each_plot)
1080 # #TODO: add multiple results support
1081 # #for fit in curve.fits:
1082 # if curve.fits.has_key('wlc'):
1083 # for plot in curve.fits['wlc'].results:
1085 # self.panelResults.DisplayResults(curve.fits['wlc'])
1087 # self.panelResults.ClearResults()
1089 # axes.figure.canvas.draw()
1091 # self.AppendToOutput('Not able to plot.')
1094 app = Hooke(debug=__debug__)
1097 if __name__ == '__main__':