Changeset a07e72f in sasview for guiframe/local_perspectives/plotting/Plotter1D.py
- Timestamp:
- Feb 28, 2011 2:07:14 PM (13 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- 243a8d4
- Parents:
- 6bbeacd4
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
guiframe/local_perspectives/plotting/Plotter1D.py
ra45037aa ra07e72f 18 18 import numpy 19 19 import time 20 import danse.common.plottools 20 21 21 from danse.common.plottools.PlotPanel import PlotPanel 22 22 from danse.common.plottools.plottables import Graph … … 26 26 from sans.guiframe.events import NewPlotEvent 27 27 from sans.guiframe.events import SlicerEvent 28 from sans.guiframe.events import ErrorDataEvent29 28 from sans.guiframe.events import RemoveDataEvent 30 29 from sans.guiframe.events import PanelOnFocusEvent … … 32 31 from sans.guiframe.utils import PanelMenu 33 32 from sans.guiframe.dataFitting import Data1D 34 from sans.guiframe.dataFitting import Theory1D35 33 from sans.guiframe.panel_base import PanelBase 36 34 from binder import BindArtist … … 67 65 #context menu 68 66 self._slicerpop = None 69 self._menu_add_plot = None67 70 68 self._available_data = [] 71 69 self._menu_add_ids = [] 72 ## save errors dy for each data plotted 73 self.err_dy = {} 74 ## flag to determine if the hide or show context menu item should 75 ## be displayed 76 self.errors_hide = False 70 self._symbol_labels = self.get_symbol_label() 71 72 self.hide_menu = None 77 73 ## Unique ID (from gui_manager) 78 74 self.uid = None 79 ## Action IDs for internal call-backs 80 self.action_ids = {} 75 81 76 ## Default locations 82 77 self._default_save_location = os.getcwd() … … 86 81 self.graph.yaxis("\\rm{Intensity} ", "cm^{-1}") 87 82 self.graph.render(self) 88 #bind with event to contrst context menu 89 #self.parent.Bind(EVT_NEW_LOADED_DATA, self._add_new_plot) 90 91 def on_add_new_plot(self, event): 92 """ 93 """ 94 def _add_new_plot(self, event): 95 """ 96 Construct the context menu given available data 97 """ 98 self._available_data = event.data_to_add 83 84 def get_symbol_label(self): 85 """ 86 Associates label to symbol 87 """ 88 _labels = {} 89 i = 0 90 _labels['Points'] = i 91 i += 1 92 _labels['X '] = i 93 i += 1 94 _labels['Triangle Down'] = i 95 i += 1 96 _labels['Triangle Up'] = i 97 i += 1 98 _labels['Triangle Left'] = i 99 i += 1 100 _labels['Triangle Right'] = i 101 i += 1 102 _labels['Plus'] = i 103 i += 1 104 _labels['Square'] = i 105 i += 1 106 _labels['Thin Diamond'] = i 107 i += 1 108 _labels['Diamond'] = i 109 i += 1 110 _labels['Hexagon1'] = i 111 i += 1 112 _labels['Hexagon2'] = i 113 i += 1 114 _labels['Pentagon'] = i 115 i += 1 116 _labels['Curve'] = i 117 return _labels 118 99 119 100 def _fill_menu_add_plot(self):101 """102 """103 if self._menu_add_plot is not None:104 if self._available_data:105 for id in self._menu_add_ids:106 item = self._menu_add_plot.FindItemById(id)107 if item is None:108 for data in self._available_data:109 new_id = wx.NewId()110 hint = 'Add %s to this panel' % str(data.name)111 self._menu_add_plot.Append(new_id, str(data.name), hint)112 wx.EVT_MENU(self, id, self.on_add_new_plot)113 self._menu_add_ids.append(new_id)114 else:115 if item.GetLabel() == 'No Loaded Data':116 self._menu_add_plot.RemoveItem(item)117 118 120 def set_data(self, list=None): 119 121 """ … … 127 129 self.graph.reset() 128 130 self.plots = {} 129 self.action_ids = {}130 131 131 def _onEVT_1DREPLOT(self, event): 132 def remove_data_by_id(self, id): 133 """' 134 remove data from plot 135 """ 136 if id in self.plots.keys(): 137 data = self.plots[id] 138 self.graph.delete(data) 139 data_manager = self._manager.parent.get_data_manager() 140 data_list = data_manager.get_by_id(id_list=[id]) 141 data = data_list.values()[0].data 142 data.group_id.remove(self.group_id) 143 del self.plots[id] 144 145 self.graph.render(self) 146 self.subplot.figure.canvas.draw_idle() 147 if len(self.graph.plottables) == 0: 148 print "_onRemove: graph is empty must be destroyed" 149 150 else: 151 msg = "Attempt to remove an unexisting plot with ID %s " % str(id) 152 raise ValueError, msg 153 154 def plot_data(self, data): 132 155 """ 133 156 Data is ready to be displayed … … 135 158 :param event: data event 136 159 """ 137 #TODO: Check for existence of plot attribute 138 # Check whether this is a replot. If we ask for a replot 139 # and the plottable no longer exists, ignore the event. 140 if hasattr(event, "update") and event.update == True \ 141 and event.plot.name not in self.plots.keys(): 142 return 143 if hasattr(event, "reset"): 144 self._reset() 145 # Check whether the plottable is empty 146 is_empty = len(event.plot.x) == 0 147 148 is_new = True 149 if event.plot.name in self.plots.keys(): 150 # If the plottable is empty, just remove the plottable from the graph 151 if is_empty: 152 self.graph.delete(self.plots[event.plot.name]) 153 del self.plots[event.plot.name] 154 else: 155 # Check whether the class of plottable changed 156 if not event.plot.__class__ == self.plots[event.plot.name].__class__: 157 #overwrite a plottable using the same name 158 self.graph.delete(self.plots[event.plot.name]) 159 else: 160 # plottable is already draw on the panel 161 is_new = False 162 163 if not is_empty: 164 if is_new: 165 # a new plottable overwrites a plotted one using the same id 166 for plottable in self.plots.itervalues(): 167 if hasattr(event.plot, "id") and hasattr(plottable, "id"): 168 #remove the existing plot and same id and same name 169 if event.plot.id == plottable.id and \ 170 event.plot.name == plottable.name: 171 self.graph.delete(plottable) 172 173 self.plots[event.plot.name] = event.plot 174 self.graph.add(self.plots[event.plot.name]) 175 else: 176 #replot the graph 177 self.plots[event.plot.name].x = event.plot.x 178 self.plots[event.plot.name].y = event.plot.y 179 self.plots[event.plot.name].dy = event.plot.dy 180 if hasattr(event.plot, 'dx') and \ 181 hasattr(self.plots[event.plot.name], 'dx'): 182 self.plots[event.plot.name].dx = event.plot.dx 183 184 #TODO: Should re-factor this 185 ## for all added plot the option to hide error show be displayed first 186 #self.errors_hide = 0 187 ## Set axis labels 188 self.graph.xaxis(event.plot._xaxis, event.plot._xunit) 189 self.graph.yaxis(event.plot._yaxis, event.plot._yunit) 160 if data.id in self.plots.keys(): 161 #replace 162 self.graph.replace(data) 163 self.plots[data.id] = data 164 else: 165 self.plots[data.id] = data 166 self.graph.add(self.plots[data.id]) 167 168 x_label, x_unit = data.get_xaxis() 169 y_label, y_unit = data.get_yaxis() 170 self.graph.xaxis(x_unit, x_label) 171 self.graph.yaxis(y_unit, y_label) 190 172 ## Set the view scale for all plots 191 173 self._onEVT_FUNC_PROPERTY() … … 193 175 self.graph.render(self) 194 176 self.subplot.figure.canvas.draw_idle() 195 #if self.errors_hide: 196 # self._on_remove_errors(evt=None) 197 #else: 198 # self._on_add_errors( evt=None) 199 177 178 200 179 def onLeftDown(self,event): 201 180 """ … … 211 190 #post nd event to notify guiframe that this panel is on focus 212 191 wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self)) 213 192 self._manager.set_panel_on_focus(self) 193 194 def _ontoggle_hide_error(self, event): 195 """ 196 Toggle error display to hide or show 197 """ 198 199 selected_plot = self.plots[self.graph.selected_plottable] 200 if self.hide_menu.GetText() == "Hide Error": 201 selected_plot.hide_error = True 202 else: 203 selected_plot.hide_error = False 204 ## increment graph color 205 self.graph.render(self) 206 self.subplot.figure.canvas.draw_idle() 207 214 208 def _onRemove(self, event): 215 209 """ … … 219 213 220 214 """ 221 selected_plot = self.plots[self.graph.selected_plottable]222 215 ## Check if there is a selected graph to remove 223 if not self.graph.selected_plottable == None and\ 224 self.graph.selected_plottable in self.plots.keys(): 225 color = self.graph.plottables[selected_plot] 216 if self.graph.selected_plottable in self.plots.keys(): 217 selected_plot = self.plots[self.graph.selected_plottable] 218 id = self.graph.selected_plottable 219 self.remove_data_by_id( id) 226 220 event = RemoveDataEvent(data=selected_plot) 227 221 wx.PostEvent(self.parent, event) 228 222 self.graph.delete(selected_plot) 229 223 del selected_plot 230 ## increment graph color 231 self.graph.color += color 232 self.graph.render(self) 233 self.subplot.figure.canvas.draw_idle() 234 224 235 225 def onContextMenu(self, event): 236 226 """ … … 253 243 self._slicerpop.Append(id, '&Print Preview', 'image preview for print') 254 244 wx.EVT_MENU(self, id, self.onPrinterPreview) 255 """ 256 #add plot 257 self._menu_add_plot = wx.Menu() 258 id = wx.NewId() 259 self._menu_add_plot.Append(id, '&No Loaded Data', 'Add new plot') 260 self._menu_add_plot.FindItemByPosition(0).Enable(False) 261 self._menu_add_ids.append(id) 262 263 self._slicerpop.AppendSubMenu(self._menu_add_plot, '&Add New Plot') 264 self._fill_menu_add_plot() 265 """ 245 246 symbol_menu = wx.Menu() 247 for label in self._symbol_labels: 248 id = wx.NewId() 249 symbol_menu.Append(id, str(label), str(label)) 250 wx.EVT_MENU(self, id, self.onChangeSymbol) 251 id = wx.NewId() 252 self._slicerpop.AppendMenu(id,'&Modify Symbol', symbol_menu) 266 253 self._slicerpop.AppendSeparator() 254 267 255 #add menu of other plugins 268 item_list = self.parent.get_context_menu(self .graph)256 item_list = self.parent.get_context_menu(self) 269 257 if (not item_list == None) and (not len(item_list) == 0): 270 258 for item in item_list: … … 275 263 except: 276 264 msg = "ModelPanel1D.onContextMenu: " 277 msg += "bad menu item %s" %sys.exc_value265 msg += "bad menu item %s" % sys.exc_value 278 266 wx.PostEvent(self.parent, StatusEvent(status=msg)) 279 267 pass 280 268 self._slicerpop.AppendSeparator() 281 269 id = wx.NewId() 282 self._menu_add_plot = wx.Menu()270 283 271 self._slicerpop.Append(id, '&Print image', 'Print image') 284 272 if self.graph.selected_plottable in self.plots: … … 287 275 name = plot.name 288 276 self._slicerpop.Append(id, "&Save points") 289 self.action_ids[str(id)] = plot290 277 wx.EVT_MENU(self, id, self._onSave) 291 278 id = wx.NewId() 292 279 self._slicerpop.Append(id, "Remove %s curve" % name) 293 self.action_ids[str(id)] = plot294 280 wx.EVT_MENU(self, id, self._onRemove) 281 id = wx.NewId() 282 self.hide_menu = self._slicerpop.Append(id, "Hide Error") 283 if plot.dy is not None or plot.dy != []: 284 if plot.hide_error : 285 self.hide_menu.SetText('Show Error') 286 else: 287 self.hide_menu.SetText('Hide Error') 288 else: 289 self.hide_menu.Disable() 290 wx.EVT_MENU(self, id, self._ontoggle_hide_error) 291 295 292 self._slicerpop.AppendSeparator() 296 293 # Option to hide 297 294 #TODO: implement functionality to hide a plottable (legend click) 298 if self.graph.selected_plottable in self.plots: 299 selected_plot = self.plots[self.graph.selected_plottable] 300 id = wx.NewId() 301 self._slicerpop.Append(id, '&Linear fit') 302 wx.EVT_MENU(self, id, self.onFitting) 303 self._slicerpop.AppendSeparator() 295 id = wx.NewId() 296 self._slicerpop.Append(id, '&Linear Fit') 297 wx.EVT_MENU(self, id, self.onFitting) 298 304 299 id = wx.NewId() 305 300 self._slicerpop.Append(id, '&Change scale') … … 311 306 pos = self.ScreenToClient(pos) 312 307 self.PopupMenu(self._slicerpop, pos) 313 314 def _on_remove_errors(self, evt): 315 """ 316 Save name and dy of data in dictionary self.err_dy 317 Create a new data1D with the same x, y 318 vector and dy with zeros. 319 post self.err_dy as event (ErrorDataEvent) for any object 320 which wants to reconstruct the initial data. 321 322 :param evt: Menu event 323 324 """ 325 if not self.graph.selected_plottable == None: 326 ## store existing dy 327 name =self.plots[self.graph.selected_plottable].name 328 dy = self.plots[self.graph.selected_plottable].dy 329 self.err_dy[name] = dy 330 ## Create a new dy for a new plottable 331 #import numpy 332 dy = numpy.zeros(len(self.plots[self.graph.selected_plottable].y)) 333 selected_plot = self.plots[self.graph.selected_plottable] 334 335 if selected_plot.__class__.__name__ == "Data1D": 336 # Make sure that we can pass a basic Data1D 337 dxl = None 338 dxw = None 339 if hasattr(selected_plot, "dxl"): 340 dxl = selected_plot.dxl 341 if hasattr(selected_plot, "dxw"): 342 dxw = selected_plot.dxw 343 new_plot = Data1D(x=selected_plot.x, y=selected_plot.y, 344 dx=selected_plot.dx, dy=dy) 345 new_plot.dxl = dxl 346 new_plot.dxw = dxw 347 else: 348 new_plot = Theory1D(x=selected_plot.x, 349 y=selected_plot.y, dy=dy) 350 new_plot.interactive = True 351 self.errors_hide = True 352 new_plot.name = self.plots[self.graph.selected_plottable].name 353 if hasattr(self.plots[self.graph.selected_plottable], "group_id"): 354 new_plot.group_id = self.plots[self.graph.selected_plottable].group_id 355 if hasattr(self.plots[self.graph.selected_plottable], "id"): 356 new_plot.id = self.plots[self.graph.selected_plottable].id 357 else: 358 new_plot.id = str(time.time()) 359 else: 360 new_plot.group_id = str(time.time()) 361 new_plot.id = str(time.time()) 362 label, unit = self.plots[self.graph.selected_plottable].get_xaxis() 363 new_plot.xaxis(label, unit) 364 label, unit = self.plots[self.graph.selected_plottable].get_yaxis() 365 new_plot.yaxis(label, unit) 366 ## save the color of the selected plottable before it is deleted 367 color = self.graph.plottables[self.plots[self.graph.selected_plottable]] 368 self.graph.delete(self.plots[self.graph.selected_plottable]) 369 ## add newly created plottable to the graph with the save color 370 self.graph.color += color 371 self.graph.add(new_plot, color) 372 ## transforming the view of the new data into the same of 373 #the previous data 374 self._onEVT_FUNC_PROPERTY() 375 ## save the plot 376 self.plots[self.graph.selected_plottable] = new_plot 377 ## Render the graph 378 self.graph.render(self) 379 self.subplot.figure.canvas.draw_idle() 380 event = ErrorDataEvent(err_dy=self.err_dy) 381 wx.PostEvent(self.parent, event) 382 383 def _on_add_errors(self, evt): 384 """ 385 create a new data1D witht the errors saved in self.err_dy 386 to show errors of the plot. 387 Compute reasonable errors for a data set without 388 errors and transorm the plottable to a Data1D 389 390 :param evt: Menu event 391 392 """ 393 if not self.graph.selected_plottable == None \ 394 and self.graph.selected_plottable in self.plots.keys(): 395 ##Reset the flag to display the hide option on the context menu 396 self.errors_hide = False 397 ## restore dy 398 length = len(self.plots[self.graph.selected_plottable].x) 399 dy = numpy.zeros(length) 400 selected_plot = self.plots[self.graph.selected_plottable] 401 try: 402 dy = self.err_dy[selected_plot.name] 403 except: 404 if hasattr(selected_plot, "dy"): 405 dy = selected_plot.dy 406 else: 407 dy = numpy.zeros(selected_plot.dy) 408 ## Create a new plottable data1D 409 if selected_plot.__class__.__name__ == "Data1D": 410 # Make sure that we can pass a basic Data1D 411 dxl = None 412 dxw = None 413 if hasattr(selected_plot, "dxl"): 414 dxl = selected_plot.dxl 415 if hasattr(selected_plot, "dxw"): 416 dxw = selected_plot.dxw 417 new_plot = Data1D(x=selected_plot.x, 418 y=selected_plot.y, 419 dx=selected_plot.dx, 420 dy=dy) 421 new_plot.dxl = dxl 422 new_plot.dxw = dxw 423 else: 424 ## Create a new plottable Theory1D 425 new_plot = Theory1D(x=selected_plot.x, y=selected_plot.y, dy=dy) 426 new_plot.interactive = True 427 new_plot.name = self.plots[self.graph.selected_plottable].name 428 if hasattr(self.plots[self.graph.selected_plottable], "group_id"): 429 new_plot.group_id = self.plots[self.graph.selected_plottable].group_id 430 if hasattr(self.plots[self.graph.selected_plottable],"id"): 431 new_plot.id = self.plots[self.graph.selected_plottable].id 432 else: 433 new_plot.id = str(time.time()) 434 else: 435 new_plot.group_id = str(time.time()) 436 new_plot.id = str(time.time()) 437 438 label, unit = self.plots[self.graph.selected_plottable].get_xaxis() 439 new_plot.xaxis(label, unit) 440 label, unit = self.plots[self.graph.selected_plottable].get_yaxis() 441 new_plot.yaxis(label, unit) 442 ## save the color of the selected plottable before it is deleted 443 color=self.graph.plottables[self.plots[self.graph.selected_plottable]] 444 self.graph.delete(self.plots[self.graph.selected_plottable]) 445 self.graph.color += color 446 ## add newly created plottable to the graph with the save color 447 self.graph.add(new_plot, color) 448 ## transforming the view of the new data into the same of 449 # the previous data 450 self._onEVT_FUNC_PROPERTY() 451 ## save the plot 452 self.plots[self.graph.selected_plottable]=new_plot 453 ## render the graph with its new content 454 self.graph.render(self) 455 self.subplot.figure.canvas.draw_idle() 456 457 308 309 def onChangeSymbol(self, event): 310 """ 311 """ 312 menu = event.GetEventObject() 313 id = event.GetId() 314 label = menu.GetLabel(id) 315 selected_plot = self.plots[self.graph.selected_plottable] 316 selected_plot.symbol = self._symbol_labels[label] 317 ## Set the view scale for all plots 318 self._onEVT_FUNC_PROPERTY() 319 ## render the graph 320 self.graph.render(self) 321 self.subplot.figure.canvas.draw_idle() 322 458 323 def _onsaveTXT(self, path): 459 324 """ … … 503 368 504 369 """ 505 id = str(evt.GetId()) 506 if id in self.action_ids: 370 371 path = None 372 wildcard = "Text files (*.txt)|*.txt|"\ 373 "CanSAS 1D files(*.xml)|*.xml" 374 dlg = wx.FileDialog(self, "Choose a file", 375 self._default_save_location, 376 "", wildcard , wx.SAVE) 377 378 if dlg.ShowModal() == wx.ID_OK: 379 path = dlg.GetPath() 380 mypath = os.path.basename(path) 507 381 508 path = None 509 wildcard = "Text files (*.txt)|*.txt|"\ 510 "CanSAS 1D files(*.xml)|*.xml" 511 dlg = wx.FileDialog(self, "Choose a file", 512 self._default_save_location, 513 "", wildcard , wx.SAVE) 514 515 if dlg.ShowModal() == wx.ID_OK: 516 path = dlg.GetPath() 517 mypath = os.path.basename(path) 518 519 #TODO: This is bad design. The DataLoader is designed 520 #to recognize extensions. 521 # It should be a simple matter of calling the . 522 #save(file, data, '.xml') method 523 # of the DataLoader.loader.Loader class. 524 from DataLoader.loader import Loader 525 #Instantiate a loader 526 loader = Loader() 527 data = self.plots[self.graph.selected_plottable] 528 format = ".txt" 529 if os.path.splitext(mypath)[1].lower() == format: 530 self._onsaveTXT( path) 531 format = ".xml" 532 if os.path.splitext(mypath)[1].lower() == format: 533 loader.save(path, data, format) 534 try: 535 self._default_save_location = os.path.dirname(path) 536 except: 537 pass 538 dlg.Destroy() 382 #TODO: This is bad design. The DataLoader is designed 383 #to recognize extensions. 384 # It should be a simple matter of calling the . 385 #save(file, data, '.xml') method 386 # of the DataLoader.loader.Loader class. 387 from DataLoader.loader import Loader 388 #Instantiate a loader 389 loader = Loader() 390 data = self.plots[self.graph.selected_plottable] 391 format = ".txt" 392 if os.path.splitext(mypath)[1].lower() == format: 393 self._onsaveTXT( path) 394 format = ".xml" 395 if os.path.splitext(mypath)[1].lower() == format: 396 loader.save(path, data, format) 397 try: 398 self._default_save_location = os.path.dirname(path) 399 except: 400 pass 401 dlg.Destroy()
Note: See TracChangeset
for help on using the changeset viewer.