class ListTraitTest(HasStrictTraits): #--------------------------------------------------------------------------- # Trait definitions: #--------------------------------------------------------------------------- people = List(Person) #--------------------------------------------------------------------------- # Traits view definitions: #--------------------------------------------------------------------------- traits_view = View(VSplit(Item('people', id='table', editor=table_editor), Item('people@', id='list', editor=ListEditor(style='custom', rows=5)), Item('people@', id='notebook', editor=ListEditor(use_notebook=True, deletable=True, export='DockShellWindow', page_name='.name')), id='splitter', show_labels=False), title='List Trait Editor Test', id='enthought.traits.ui.tests.list_traits_ui_test', dock='horizontal', width=.4, height=.6, resizable=True, buttons=NoButtons, kind='live')
class ThreadDemo ( HasTraits ): # The button used to start a new thread running: create = Button( 'Create Thread' ) # The set of counter objects currently running: counters = List( Counter ) view = View( Item( 'create', show_label = False, width = -100 ), '_', Item( 'counters', style = 'custom', show_label = False, editor = ListEditor( use_notebook = True, dock_style = 'tab' ) ), resizable=True ) def __init__ ( self, **traits ): super( HasTraits, self ).__init__( **traits ) # Set up the notification handler for the 'Create Thread' button so # that it is run on a new thread: self.on_trait_change( self.count, 'create', dispatch = 'new' ) def count ( self ): """ This method is dispatched on a new thread each time the 'Create Thread' button is pressed. """ counter = Counter() self.counters.append( counter ) for i in range( 1000 ): counter.count += 1 sleep( 0.030 ) self.counters.remove( counter )
class InternetExplorerDemo ( HasTraits ): # A URL to display: url = Str( 'http://' ) # The list of web pages being browsed: pages = List( WebPage ) # The view to display: view = View( VGroup( Item( 'url', label = 'Location', editor = TextEditor( auto_set = False, enter_set = True ) ) ), Item( 'pages', show_label = False, style = 'custom', editor = ListEditor( use_notebook = True, deletable = True, dock_style = 'tab', export = 'DockWindowShell', page_name = '.title' ) ) ) # Event handlers: def _url_changed ( self, url ): self.pages.append( WebPage( url = url.strip() ) )
class AnalogInputViewer(traits.HasTraits): channels = traits.List usb_device_number2index = traits.Property(depends_on='channels') @traits.cached_property def _get_usb_device_number2index(self): result = {} for i, channel in enumerate(self.channels): result[channel.device_channel_num] = i return result traits_view = View( Group( Item( 'channels', style='custom', editor=ListEditor(rows=3, editor=InstanceEditor(), style='custom'), resizable=True, )), resizable=True, width=800, height=600, title='Analog Input', ) def __init__(self, *args, **kwargs): super(AnalogInputViewer, self).__init__(*args, **kwargs) for usb_channel_num in [0, 1, 2, 3]: self.channels.append( AnalogInputChannelViewer(device_channel_num=usb_channel_num))
class Hotel(HasPrivateTraits): # The season of the year: season = Enum('Winter', 'Spring', 'Summer', 'Fall') # The current cost of heating fuel (in dollars/gallon): fuel_cost = Range(2.00, 10.00, 4.00) # The current minimum temparature allowed by the hotel: min_temperature = Property(depends_on='season, fuel_cost') # The guests currently staying at the hotel: guests = List # ( Instance( 'Guest' ) ) # Add a new guest to the hotel: add_guest = Button('Add Guest') # The view of the hotel: view = View(VGroup( HGroup(Item('season'), '20', Item('fuel_cost', width=300), spring, Item('add_guest', show_label=False), show_border=True, label='Hotel Information'), VGroup(Item('guests', style='custom', editor=ListEditor(use_notebook=True, deletable=True, dock_style='tab', page_name='.name')), show_labels=False, show_border=True, label='Guests')), title='The Belmont Hotel Dashboard', width=0.6, height=0.2, resizable=True) # Property implementations: @cached_property def _get_min_temperature(self): return ({ 'Winter': 32, 'Spring': 40, 'Summer': 45, 'Fall': 40 }[self.season] + min(int(60.00 / self.fuel_cost), 15)) # Event handlers: @on_trait_change('guests[]') def _guests_modified(self, removed, added): for guest in added: guest.hotel = self def _add_guest_changed(self): self.guests.append(Guest())
def default_traits_view(self): return View( Group(Group(Item('open_file', style='custom'), show_labels=False, show_border=False), Item('items_list', style='readonly', editor=ListEditor(style='custom')), show_labels=False, label='Add a data source'))
def default_traits_view(self): """Returns the default traits view for this object.""" le = ListEditor(use_notebook=True, deletable=False, export='DockWindowShell', page_name='.name') view = View(Group(Item(name='filters', style='custom', show_label=False, editor=le, resizable=True), show_labels=False), resizable=True) return view
class ListTraitTest(HasStrictTraits): # Trait definitions: people = List(Instance(Person, ())) # Traits view definitions: traits_view = View( Tabbed(Item('people', label='Table', id='table', editor=table_editor), Item('people@', label='List', id='list', editor=ListEditor(style='custom', rows=5)), Item('people@', label='Notebook', id='notebook', editor=ListEditor(use_notebook=True, deletable=True, export='DockShellWindow', page_name='.name')), id='splitter', show_labels=False), id='enthought.traits.ui.demo.Traits UI Demo.Advanced.List_editors_demo', dock='horizontal')
def default_traits_view(self): view = View(VSplit( HGroup( Group( spring, Item('delimiter', label='Column delimiter character'), Item('comments', label='Comment character'), Item('skiprows', label='Number of lines to skip at the ' 'beginning of the file'), spring, Item('handler.update_preview', show_label=False), ), Group( Item( 'columns', show_label=False, style='readonly', editor=ListEditor(style='custom'), springy=True, ), label="Column names", show_border=True, ), ), Group(Group( Item( 'data', show_label=False, editor=self.tabular_editor, ), label="Preview table", ), Group( Item('handler.file_content', style='readonly', show_label=False, springy=True), label="%s" % self.model.filename, ), layout='tab'), ), buttons=['OK', 'Cancel', 'Help'], id='csv_load_editor', resizable=True, width=640, height=580, title='CSV import - [%s]' % self.model.filename) return view
class ChannelNamesEditor(HasTraits): """ChannelNamesEditor Used to edit the channel-names of EEG files.""" # THE trait-attribute to change channel_names = List(Str) view = View( Item( 'channel_names@', #show_label = False, editor=ListEditor(style="text")), title='Editing channel-names', width=0.5, height=0.6, resizable=True, buttons=[OKButton, CancelButton, RevertButton, UndoButton])
class CSVGrapher(HasTraits): """ 主界面包括绘图列表,数据源,文件选择器和添加绘图按钮 """ graph_list = List(Instance(Graph)) # 绘图列表 data_source = Instance(DataSource) # 数据源 csv_file_name = File(filter=[u"*.csv"]) # 文件选择 add_graph_button = Button(u"添加绘图") # 添加绘图按钮 view = View( # 整个窗口分为上下两个部分 VGroup( # 上部分横向放置控件,因此用HGroup HGroup( # 文件选择控件 Item("csv_file_name", label=u"选择CSV文件", width=400), # 添加绘图按钮 Item("add_graph_button", show_label=False) ), # 下部分是绘图列表,采用ListEditor编辑器显示 Item("graph_list", style="custom", show_label=False, editor=ListEditor( use_notebook=True, # 是用多标签页格式显示 deletable=True, # 可以删除标签页 dock_style="tab", # 标签dock样式 page_name=".name") # 标题页的文本使用Graph对象的name属性 ) ), resizable = True, height = 0.8, width = 0.8, title = u"CSV数据绘图器" ) def _csv_file_name_changed(self): """ 打开新文件时的处理,根据文件创建一个DataSource """ self.data_source = DataSource() self.data_source.load_csv(self.csv_file_name) del self.graph_list[:] def _add_graph_button_changed(self): """ 添加绘图按钮的事件处理 """ if self.data_source != None: self.graph_list.append( Graph(data_source = self.data_source) )
class ListEditorNotebookSelectionDemo(HasStrictTraits): #-- Trait Definitions ------------------------------------------------------ # List of people: people = List(Person) # The currently selected person: selected = Instance(Person) # The index of the currently selected person: index = Range(0, 7, mode='spinner') #-- Traits View Definitions ------------------------------------------------ traits_view = View(Item('index'), '_', VGroup( Item('people@', id='notebook', show_label=False, editor=ListEditor(use_notebook=True, deletable=False, selected='selected', export='DockWindowShell', page_name='.name'))), id='enthought.traits.ui.demo.Traits UI Demo.Advanced.' 'List_editor_notebook_selection_demo', dock='horizontal') #-- Trait Event Handlers --------------------------------------------------- def _selected_changed(self, selected): self.index = self.people.index(selected) def _index_changed(self, index): self.selected = self.people[index]
class TVTKViewer(Viewer): name = Str('TVTK Viewer') primitives = List(Primitive) scene = Instance(SceneModel, ()) view = View( Item(name='scene', height=400, show_label=False, editor=SceneEditor())) traits_view = View(Item(name='name'), Item(name='refresh_rate'), Item(name='primitives', editor=ListEditor(), style='custom'), title='Viewer') def start(self): from plotconfig import TVTKconfig self.config = TVTKconfig(self.variables) self.primitives = self.config.getPrimitives() for prim in self.primitives: self.scene.add_actors(prim.actor) def stop(self): pass def show(self): pass def hide(self): pass def update(self): for prim in self.primitives: prim.update() GUI.invoke_later(self.scene.render)
class App(HasTraits): docs = List(Instance(Doc)) XCAFApp = Instance(XCAFApp.XCAFApp_Application) traits_view = View(Item('docs', style="custom", editor=ListEditor(use_notebook=True), show_label=False), height=600, width=1000, resizable=True) def _XCAFApp_default(self): return XCAFApp.GetApplication().GetObject() def LoadSTEPFile(self, fname): reader = STEPCAFControl.STEPCAFControl_Reader() reader.ReadFile(str(fname)) h_doc = self.MakeNewDocHandle() reader.Transfer(h_doc) doc = h_doc.GetObject() self.docs.append(Doc(filename=fname, TDocStd=doc)) def MakeNewDocHandle(self): h_doc = TDocStd.Handle_TDocStd_Document() schema = TCollection.TCollection_ExtendedString("MDTV-CAF") self.XCAFApp.NewDocument(schema, h_doc) return h_doc def MakeNewDoc(self): h_doc = self.MakeNewDocHandle() return h_doc.GetObject()
class VTKDataObject(DataObject): yt_scene = Instance(YTScene) scene = DelegatesTo("yt_scene") add_contours = Button add_isocontour = Button add_x_plane = Button add_y_plane = Button add_z_plane = Button edit_camera = Button edit_operators = Button edit_pipeline = Button center_on_max = Button operators = DelegatesTo("yt_scene") traits_view = View( Item("scene", editor=SceneEditor(scene_class=DecoratedScene), resizable=True, show_label=False), HGroup( Item("add_contours", show_label=False), Item("add_isocontour", show_label=False), Item("add_x_plane", show_label=False), Item("add_y_plane", show_label=False), Item("add_z_plane", show_label=False), Item("edit_camera", show_label=False), Item("edit_operators", show_label=False), Item("edit_pipeline", show_label=False), Item("center_on_max", show_label=False), ), ) operators_edit = View(Item("operators", style='custom', show_label=False, editor=ListEditor(editor=InstanceEditor(), use_notebook=True), name="Edit Operators"), height=500.0, width=500.0, resizable=True) def _edit_camera_fired(self): self.yt_scene.camera_path.edit_traits() def _edit_operators_fired(self): self.edit_traits(view='operators_edit') def _edit_pipeline_fired(self): from enthought.tvtk.pipeline.browser import PipelineBrowser pb = PipelineBrowser(self.scene) pb.show() def _add_contours_fired(self): self.yt_scene.add_contour() def _add_isocontour_fired(self): self.yt_scene.add_isocontour() def _add_x_plane_fired(self): self.yt_scene.add_x_plane() def _add_y_plane_fired(self): self.yt_scene.add_y_plane() def _add_z_plane_fired(self): self.yt_scene.add_z_plane() def _center_on_max_fired(self): self.yt_scene.do_center_on_max()
class Images(HasTraits): """Main class for image point selections """ filenames = Instance(Filenames, ()) analysis = Instance(RectangleSelections, transient=True) filters = List(Instance(BaseFilter)) figure = Instance(Figure, transient=True) data = Array def _filters_default(self): return [Rotate(), GaussianFilter()] def _analysis_default(self): return RectangleSelections() def _figure_default(self): def selection_callback(pos1, pos2): try: if pos1 == pos2: self.analysis.selection.set_from_points(pos1) else: self.analysis.selection.set_from_points(pos1, pos2) except: pass figure = Figure(process_selection=selection_callback) return figure @on_trait_change('filenames.selected') def open_image(self): data = imread(self.filenames.selected) for f in self.filters: data = f.process(data) self.data = data @on_trait_change('data,analysis.updated') def image_show(self): try: self.figure.plot_image(self.data) except: pass @on_trait_change('analysis.updated') def show_selection2(self): def plot(selection, color, index): s = selection x, y = list( map(lambda *args: args, s.top_left, s.top_right, s.bottom_right, s.bottom_left, s.top_left)) self.figure.plot_data(x, y, str(index), color) for i in range(len(self.analysis.selections) + 1): self.figure.del_plot(str(i)) for index, selection in enumerate(self.analysis.selections): if self.analysis.index == index: color = 'red' else: color = 'black' try: plot(selection, color, index) except: pass view = View( VSplit(HSplit(Item('figure', style='custom', width=0.6, height=0.7), Group(Item('analysis', style="custom", resizable=True, width=0.4, height=0.7, show_label=False), scrollable=True), show_labels=False), HSplit( Group( Item('filenames', style='custom', show_label=False, height=0.3)), Item('filters@', id='notebook', show_label=False, editor=ListEditor(use_notebook=True, deletable=False, selected='selected', export='DockWindowShell', page_name='.name_'))), show_labels=False), width=1000, height=800, resizable=True, )
class RectangleSelections(HasTraits): """ Object used to store analysis objects in List of points """ selections = List(RectangleSelection) selection = Instance(RectangleSelection,transient = True) #: default filename for points load, save filename = File() add_point = Button() load = Button() save = Button() index_high = Property(Int,depends_on = 'selections',transient = True) index = Property(Int, depends_on = 'selection,index_high',transient = True) updated = Event() _update = Bool(True) view = View( Item('index' , editor = RangeEditor( low = 0, high_name = 'index_high', is_float = False, mode = 'spinner' )), HGroup( Item('add_point', show_label = False, springy = True), Item('load', show_label = False, springy = True), Item('save', show_label = False, springy = True), ), '_', VGroup( Item( 'selections@', id = 'notebook', show_label = False, editor = ListEditor( use_notebook = True, deletable = True, selected = 'selection', export = 'DockWindowShell', page_name = '.name' ) ), ), dock = 'horizontal' , resizable = True, height = -0.5) def _load_fired(self): f = FileDialog(action = 'open', title = 'Load points', default_path = self.filename, wildcard = '*.points') if f.open() == OK: self.filename = f.path self.from_file(f.path) def _save_fired(self): f = FileDialog(action = 'save as', title = 'Save points', default_path = self.filename, wildcard = '*.points') if f.open() == OK: self.filename = f.path self.to_file(f.path, self.selections) def _selection_default(self): return self.selections[0] def _get_index_high(self): return len(self.selections)-1 def _add_point_fired(self): self._update = False point = (self.selections[self.index]).clone_traits() point.name = 'point ' + str(len(self.selections)) self.selections.append(point) self.selection = self.selections[-1] self._update = True self.update() def _selections_default(self): return POINTS # @on_trait_change('selections[]') # def _update_names(self): # #update point names # for i, point in enumerate(self.selections): # point.name = 'point ' + str(i) def _get_index(self): try: return self.selections.index(self.selection) except: return self.index_high self.update() def _set_index(self, value): self.selection = self.selections[value] def from_file(self, filename): """Reads selections from file """ selections = [] with open(filename, 'rb') as f: for line in f: selections.append(RectangleSelection(**safe_eval(line))) self.selections = selections self._update = True self.update() return selections def to_file(self, filename, selections): """Stores selections to file """ with open(filename, 'wb') as f: for s in selections: kw = s.get('width', 'height', 'name') kw['center'] = tuple(s.center) f.write(str(kw)) f.write('\n') @on_trait_change('selection.updated') def update(self): """ Notify update """ if self._update: self.updated = True
class MayaviViewer(HasTraits): """ This class represents a Mayavi based viewer for the particles. They are queried from a running solver. """ particle_arrays = List(Instance(ParticleArrayHelper), []) pa_names = List(Str, []) client = Instance(MultiprocessingClient) host = Str('localhost', desc='machine to connect to') port = Int(8800, desc='port to use to connect to solver') authkey = Password('pysph', desc='authorization key') host_changed = Bool(True) scene = Instance(MlabSceneModel, ()) controller = Property() ######################################## # Timer traits. timer = Instance(Timer) interval = Range(2, 20.0, 5.0, desc='frequency in seconds with which plot is updated') ######################################## # Solver info/control. current_time = Float(0.0, desc='the current time in the simulation') iteration = Int(0, desc='the current iteration number') pause_solver = Bool(False, desc='if the solver should be paused') ######################################## # The layout of the dialog created view = View(HSplit( Group( Group( Item(name='host'), Item(name='port'), Item(name='authkey'), label='Connection', ), Group( Item(name='current_time'), Item(name='iteration'), Item(name='pause_solver'), Item(name='interval'), label='Solver', ), Group( Item(name='particle_arrays', style='custom', show_label=False, editor=ListEditor(use_notebook=True, deletable=False, page_name='.name'))), ), Item('scene', editor=SceneEditor(scene_class=MayaviScene), height=480, width=500, show_label=False), ), resizable=True, title='Mayavi Particle Viewer') ###################################################################### # `MayaviViewer` interface. ###################################################################### @on_trait_change('scene.activated') def start_timer(self): # Just accessing the timer will start it. t = self.timer if not t.IsRunning(): t.Start(int(self.interval * 1000)) @on_trait_change('scene.activated') def update_plot(self): # do not update if solver is paused if self.pause_solver: return controller = self.controller if controller is None: return self.current_time = controller.get_t() for idx, name in enumerate(self.pa_names): pa = controller.get_named_particle_array(name) self.particle_arrays[idx].particle_array = pa ###################################################################### # Private interface. ###################################################################### @on_trait_change('host,port,authkey') def _mark_reconnect(self): self.host_changed = True def _get_controller(self): ''' get the controller, also sets the iteration count ''' reconnect = self.host_changed if not reconnect: try: c = self.client.controller self.iteration = c.get_count() except Exception as e: logger.info( 'Error: no connection or connection closed: reconnecting') reconnect = True self.client = None if reconnect: self.host_changed = False try: if MultiprocessingClient.is_available((self.host, self.port)): self.client = MultiprocessingClient(address=(self.host, self.port), authkey=self.authkey) else: return None except Exception as e: logger.info('Could not connect: check if solver is running') return None c = self.client.controller self.iteration = c.get_count() return self.client.controller def _client_changed(self, old, new): if self.client is None: return else: self.pa_names = self.client.controller.get_particle_array_names() self.scene.mayavi_scene.children[:] = [] self.particle_arrays = [ ParticleArrayHelper(scene=self.scene, name=x) for x in self.pa_names ] # Turn on the legend for the first particle array. if len(self.particle_arrays) > 0: self.particle_arrays[0].show_legend = True def _timer_event(self): # catch all Exceptions else timer will stop try: self.update_plot() except Exception as e: logger.info('Exception: %s caught in timer_event' % e) def _interval_changed(self, value): t = self.timer if t is None: return if t.IsRunning(): t.Stop() t.Start(int(value * 1000)) def _timer_default(self): return Timer(int(self.interval * 1000), self._timer_event) def _pause_solver_changed(self, value): c = self.client.controller if value: c.pause_on_next() else: c.cont()
class TVTKClassChooser(HasTraits): # The selected object, is None if no valid class_name was made. object = Property # The TVTK class name to choose. class_name = Str('', desc='class name of TVTK class (case sensitive)') # The string to search for in the class docs -- the search supports # 'and' and 'or' keywords. search = Str('', desc='string to search in TVTK class documentation '\ 'supports the "and" and "or" keywords. '\ 'press <Enter> to start search. '\ 'This is case insensitive.') clear_search = Button # The class documentation. doc = Str(_search_help_doc) # Completions for the choice of class. completions = List(Str) # List of available class names as strings. available = List(TVTK_CLASSES) ######################################## # Private traits. finder = Instance(DocSearch) n_completion = Int(25) ######################################## # View related traits. view = View(Group(Item(name='class_name', editor=EnumEditor(name='available')), Item(name='class_name', has_focus=True ), Item(name='search', editor=TextEditor(enter_set=True, auto_set=False) ), Item(name='clear_search', show_label=False), Item('_'), Item(name='completions', editor=ListEditor(columns=3), style='readonly' ), Item(name='doc', resizable=True, label='Documentation', style='custom') ), id='tvtk_doc', resizable=True, width=800, height=600, title='TVTK class chooser', buttons = ["OK", "Cancel"] ) ###################################################################### # `object` interface. ###################################################################### def __init__(self, **traits): super(TVTKClassChooser, self).__init__(**traits) self._orig_available = list(self.available) ###################################################################### # Non-public interface. ###################################################################### def _get_object(self): o = None if len(self.class_name) > 0: try: o = getattr(tvtk, self.class_name)() except (AttributeError, TypeError): pass return o def _class_name_changed(self, value): av = self.available comp = [x for x in av if x.startswith(value)] self.completions = comp[:self.n_completion] if len(comp) == 1 and value != comp[0]: self.class_name = comp[0] o = self.object if o is not None: self.doc = get_tvtk_class_doc(o) else: self.doc = _search_help_doc def _finder_default(self): return DocSearch() def _clear_search_fired(self): self.search = '' def _search_changed(self, value): if len(value) < 3: self.available = self._orig_available return f = self.finder result = f.search(value) if len(result) == 0: self.available = self._orig_available elif len(result) == 1: self.class_name = result[0] else: self.available = result self.completions = result[:self.n_completion]
class Application(HasTraits): scene = Instance(MlabSceneModel, (), editor=SceneEditor()) # The mayavi engine view. engine_view = Instance(EngineView) coils = List(Instance(Loop, (), allow_none=False), editor=ListEditor(style='custom'), value=[ Loop(position=(0, 0, -0.05), ), Loop(position=(0, 0, 0.05), ), ]) Bx = Array(value=np.zeros_like(X)) By = Array(value=np.zeros_like(X)) Bz = Array(value=np.zeros_like(X)) Bnorm = Array(value=np.zeros_like(X)) vector_field = None def __init__(self, **traits): HasTraits.__init__(self, **traits) self.engine_view = EngineView(engine=self.scene.engine) @on_trait_change('scene.activated,coils') def init_view(self): if self.scene._renderer is not None: self.scene.scene_editor.background = (0, 0, 0) for coil in self.coils: coil.app = self coil.display() self.visualize_field() def visualize_field(self): self.Bx = np.zeros_like(X) self.By = np.zeros_like(X) self.Bz = np.zeros_like(X) self.Bnorm = np.zeros_like(X) self.scene.scene.disable_render = True for coil in self.coils: self.Bx += coil.Bx self.By += coil.By self.Bz += coil.Bz self.Bnorm = np.sqrt(self.Bx**2 + self.By**2 + self.Bz**2) if self.vector_field is None: self.vector_field = self.scene.mlab.pipeline.vector_field( X, Y, Z, self.Bx, self.By, self.Bz, scalars=self.Bnorm, name='B field') vectors = self.scene.mlab.pipeline.vectors( self.vector_field, mode='arrow', resolution=10, mask_points=6, colormap='YlOrRd', scale_factor=2 * np.abs(X[0, 0, 0] - X[1, 1, 1])) vectors.module_manager.vector_lut_manager.reverse_lut = True vectors.glyph.mask_points.random_mode = False self.scene.mlab.axes() self.scp = self.scene.mlab.pipeline.scalar_cut_plane( self.vector_field, colormap='hot') else: # Modify in place the data source. The visualization will # update automaticaly self.vector_field.mlab_source.set(u=self.Bx, v=self.By, w=self.Bz, scalars=self.Bnorm) self.scene.scene.disable_render = False view = View( HSplit(VSplit(Item(name='engine_view', style='custom', resizable=True), Item('coils', springy=True), show_labels=False), 'scene', show_labels=False), resizable=True, title='Coils...', height=0.8, width=0.8, )
class FieldOperations(Filter): """ Performs standard field operations. Use this filter in conjunction with SetActiveAttribute filter to view new/modified fields. """ # The version of this class. Used for persistence. __version__ = 0 grid = Instance(tvtk.UnstructuredGrid, allow_none=False) operation = Enum('Sum', 'Multiply', 'Grad', 'Div', 'Curl', 'd/dx', 'd/dy', 'd/dz', 'Normalize', '2-norm', 'Reciprocal', 'Dot product', 'Cross product', 'Step', 'Natural log', 'Exponential', 'Scale/Offset', 'x-component', 'y-component', 'z-component', 'Python function') custom_function = Code( '\n# Define a single-line operation in terms of\n# the variable \'inputs\' which is an array of\n# input arrays. math and numpy are imported.\n# The operation must return a single array.\n' ) # Input and output fields scale_factor = Float(1.0) offset = Float(0.0) field_name = String input_field = Tuple(field_name, scale_factor, offset) input_fields = List(input_field) output_field = Tuple(field_name, scale_factor, offset) # Buttons apply = Button clear = Button # Saving output_file = File save = Button # Renaming rename_field_old = String rename_field_new = String rename = Button # Deleting remove_field = String remove = Button ###################################################################### # The view. ###################################################################### field_editor = TupleEditor(labels=['Name', 'Scale factor', 'Offset']) field_list_editor = ListEditor(style='custom', rows=3, editor=field_editor) traits_view = \ View( Group( Item(name='operation'), Group( Item(name='custom_function'), visible_when='operation==\'Python function\'', show_labels=False ), Group( Item(name='input_fields', style='custom', editor=field_list_editor), show_labels=False, show_border=True, label='Input fields' ), Group( Item(name='output_field', style='custom', editor=field_editor), show_labels=False, show_border=True, label='Output field' ), Group( Item(name='apply', label='Apply operation'), Item(name='clear', label='Clear'), show_labels=False ), label='Operation' ), Group( Group( Item(name='output_file'), Item(name='save', label='Save'), show_labels=False, show_border=True, label='Save changes to file' ), Group( Group( Item(name='rename_field_old', label='Field to rename'), Item(name='rename_field_new', label='New name') ), Item(name='rename', label='Rename'), show_labels=False, show_border=True, label='Rename field' ), Group( Group( Item(name='remove_field', label='Field to remove') ), Item(name='remove', label='Remove'), show_labels=False, show_border=True, label='Remove field' ), label='Misc' ), height=600, width=550 ) dialog_msg = String ###################################################################### # `Filter` interface. ###################################################################### def setup_pipeline(self): print 'setup_pipeline' def update_pipeline(self): print 'update_pipeline' if len(self.inputs) == 0 or len(self.inputs[0].outputs) == 0: return self.grid = tvtk.UnstructuredGrid() ## Way of doing this without a deep_copy (idea: copy input to output, with additional arrays tagged on)? self.grid.deep_copy(self.inputs[0].outputs[0]) # Add a blank input field by default self.input_fields.append(self.input_field) self._set_outputs([self.grid]) def update_data(self): print 'update_data' self.data_changed = True ###################################################################### # Non-public interface. ###################################################################### def _apply_fired(self): try: self.field_operation(self.operation, self.input_fields, self.output_field) self._dialog_box( 'Success', 'Operation complete. The result has been stored in \'' + self.output_field[0] + '\'.') except Exception, inst: self._dialog_box('Error', inst.__str__())
class Plot(Viewer): name = Str('Plot') plot = Instance(chaco.Plot) plot_data = Instance(chaco.ArrayPlotData, ()) y_exprs = List(Instance(Expression)) x_expr = Instance(Expression) x_label = Str x_max = Float x_max_auto = Bool(True) x_min = Float x_min_auto = Bool(True) y_label = Str y_max = Float y_max_auto = Bool(True) y_min = Float y_min_auto = Bool(True) scroll = Bool(True) scroll_width = Float(300) legend = Bool(False) index_range = DelegatesTo('plot') traits_view = View( Item(name = 'name', label = 'Plot name'), Item(label = 'Use commas\nfor multi-line plots.'), Item(name = 'legend', label = 'Show legend'), VGroup( Item(name = 'index_range', label = 'Index range', editor = InstanceEditor()), Item(name = 'x_expr', label = 'Expression', style = 'custom'), HGroup( Item(name = 'x_max', label = 'Max'), Item(name = 'x_max_auto', label = 'Auto') ), HGroup( Item(name = 'x_min', label = 'Min'), Item(name = 'x_min_auto', label = 'Auto') ), HGroup( Item(name = 'scroll', label = 'Scroll'), Item(name = 'scroll_width', label = 'Scroll width'), ), Item(name = 'x_label', label = 'Label'), label = 'X', show_border = True ), VGroup( Item(name = 'y_exprs', label = 'Expression(s)', style = 'custom', editor=ListEditor(style = 'custom')), HGroup( Item(name = 'y_max', label = 'Max'), Item(name = 'y_max_auto', label = 'Auto') ), HGroup( Item(name = 'y_min', label = 'Min'), Item(name = 'y_min_auto', label = 'Auto') ), Item(name = 'y_label', label = 'Label'), label = 'Y', show_border = True ), title = 'Plot settings', resizable = True ) view = View( Item( 'plot', editor = ComponentEditor(bgcolor = (0.8,0.8,0.8)), show_label = False, ), resizable = True ) @on_trait_change('name') def update_name(self, new_name): if self.plot: self.plot.title = new_name #GUI.invoke_later(self.plot.request_redraw) @on_trait_change('x_label') def update_x_label(self, new_name): if self.plot: self.plot.index_axis.title = new_name #GUI.invoke_later(self.plot.request_redraw) @on_trait_change('y_label') def update_y_label(self, new_name): if self.plot: self.plot.value_axis.title = new_name #GUI.invoke_later(self.plot.request_redraw) def start(self): self.plot = chaco.Plot(self.plot_data, title=self.name, auto_colors=colours_list) self.plot.value_range.tight_bounds = False #legend = chaco.Legend(component=self.plot, padding=10, align="ul") #legend.tools.append(LegendTool(legend, drag_button="right")) #self.plot.overlays.append(legend) #self.y_exprs += [self.variables.new_expression('a')] #self.x_expr = self.variables.new_expression('i') self.update_y_exprs() def get_config(self): exprs = [expr._expr for expr in self.y_exprs] return { 'name': self.name, 'x_label': self.x_label, 'y_label': self.y_label, 'expressions': exprs } def set_config(self, config): exprs = [self.variables.new_expression(expr) for expr in config['expressions']] self.y_exprs = exprs self.name = config['name'] self.x_label = config['x_label'] self.y_label = config['y_label'] def add_expr(self, expr): self.y_exprs.append(self.variables.new_expression(expr)) self.update_y_exprs() @on_trait_change('y_exprs') def update_y_exprs(self): if self.plot: if self.plot.plots: for plot in list(self.plot.plots.iterkeys()): self.plot.delplot(plot) for n, expr in enumerate(self.y_exprs): if expr is None: # Initialise a new expression if we added one self.y_exprs[n] = self.variables.new_expression('0.5') ys = self.y_exprs[n].get_array() self.plot_data.set_data(str(n), ys) self.plot_data.set_data('x', range(len(ys))) self.plot.plot(('x', str(n)), name = str(n), style='line', color='auto') #self.update() @on_trait_change('x_expr') def update_x_expr(self): self.update() def get_x_bounds(self, x_low, x_high, margin, tight_bounds): if self.scroll: x_max = max(xs) x_min = x_max = self.scroll_width if x_min < 0: x_min = 0 else: x_max = self.x_max x_min = self.x_min if self.x_max_auto: x_max = max(xs) if self.x_min_auto: x_min = min(xs) return (x_min, x_max) def get_y_bounds(self, y_low, y_high, margin, tight_bounds): y_max = self.y_max y_min = self.y_min if self.y_max_auto: y_max = max(ys) if self.y_min_auto: y_min = min(ys) return (y_min, y_max) def update(self): if self.plot: ys = numpy.array([]) last = self.variables.sample_number for n, expr in enumerate(self.y_exprs): ys = self.y_exprs[n].get_array(last = last) self.plot_data.set_data(str(n), ys) self.plot_data.set_data('x', numpy.arange(len(ys)))
arrange_item = Item("arrange", show_label=False) redraw_item = Item("redraw", show_label=False) nodes_item = Item(name="nodes", editor=node_table_editor, show_label=False) edges_item = Item(name="edges", editor=edge_table_editor, show_label=False) #------------------------------------------------------------------------------ # Groups: #------------------------------------------------------------------------------ subgraphs_notebook_group = Group(Item("subgraphs@", id=".subgraphs_nb", show_label=False, editor=ListEditor( use_notebook=True, deletable=True, export='DockShellWindow', page_name='.ID')), label="Subgraphs", id=".subgraphs") clusters_notebook_group = Group(Item("clusters@", id=".clusters_nb", show_label=False, editor=ListEditor( use_notebook=True, deletable=True, export="DockShellWindow", page_name=".ID")), label="Clusters", id=".clusters")
class TFColors(HasTraits): gaussians = List(Instance(TFGaussian)) transfer_function = Instance(ColorTransferFunction) left_edge = Float(0.0) right_edge = Float(10.0) add_gaussian = Button run_routine = Button save_function = Button routine = Callable plot_data = Instance(ArrayPlotData) image_data = Instance(ArrayPlotData) vr_image_data = Instance(ArrayPlotData) plot = Instance(Plot) image_plot = Instance(Plot) vr_image_plot = Instance(Plot) traits_view = View(VGroup( HGroup( VGroup( Item('image_plot', editor=ComponentEditor(), show_label=False, resizable=True), Item('plot', editor=ComponentEditor(), show_label=False, resizable=True), ), Item('vr_image_plot', editor=ComponentEditor(size=(512,512)), show_label=False, resizable=False, width=512, height=512)), Item("gaussians", style='custom', editor=ListEditor(style='custom'), show_label=False, ), HGroup(Item("left_edge"), Item("right_edge")), HGroup(Item("add_gaussian", show_label = False), Item("run_routine", show_label = False), Item("save_function", show_label = False), ), ), width=960, height=800, resizable=True) def _plot_data_default(self): return ArrayPlotData(rx = (0.0, 1.0), ry = (0.0, 0.0), gx = (0.0, 1.0), gy = (0.0, 0.0), bx = (0.0, 1.0), by = (0.0, 0.0), ax = (0.0, 1.0), ay = (0.0, 0.0), lx = (0.0, 1.0), ly = (0.0, 0.0), ux = (0.0, 1.0), uy = (1.0, 1.0)) def _image_data_default(self): return ArrayPlotData(image_data = na.zeros((40,256,4), dtype='uint8')) def _vr_image_data_default(self): return ArrayPlotData(vr_image_data = na.zeros((512,512,3), dtype='uint8')) def _plot_default(self): p = Plot(self.plot_data) p.plot( ("rx", "ry"), type='line', color='red') p.plot( ("gx", "gy"), type='line', color='green') p.plot( ("bx", "by"), type='line', color='blue') p.plot( ("ax", "ay"), type='line', color='black') p.plot( ("lx", "ly"), type='line', color='black') p.plot( ("ux", "uy"), type='line', color='black') return p def _image_plot_default(self): plot = Plot(self.image_data, default_origin="top left") #plot.x_axis.orientation = "top" img_plot = plot.img_plot("image_data")[0] plot.bgcolor = "black" return plot def _vr_image_plot_default(self): plot = Plot(self.vr_image_data, default_origin="top left", size=(512,512)) plot.aspect_ratio = 1.0 #plot.x_axis.orientation = "top" img_plot = plot.img_plot("vr_image_data")[0] plot.bgcolor = "black" return plot def _add_gaussian_fired(self): self.gaussians.append(TFGaussian(tf = self)) def _redraw(self): self.transfer_function = ColorTransferFunction( (self.left_edge, self.right_edge)) for g in self.gaussians: self.transfer_function.add_gaussian(g.center, g.width, (g.red, g.green, g.blue, g.alpha)) for f, c in zip(self.transfer_function.funcs, "rgba"): self.plot_data["%sx" % c] = f.x self.plot_data["%sy" % c] = f.y # Now we update the image describing the colors # This makes the assumption that all the x values are the same image = na.zeros((40, self.transfer_function.nbins, 4), dtype='uint8') for i,f in enumerate(self.transfer_function.funcs): image[:,:,i] = (f.y[None,:] * 255).astype('uint8') self.image_data["image_data"] = image def _run_routine_fired(self): img_data = self.routine(self.transfer_function) self.vr_image_data['vr_image_data'] = img_data def _save_function_fired(self): self._redraw() dlg = pyface.FileDialog( action='save as', wildcard="*.ctf", ) if dlg.open() == pyface.OK: print "Saving:", dlg.path tf = self.transfer_function f = open(dlg.path, "wb") cPickle.dump(tf, f)
class KeyBindings(HasStrictTraits): """ A set of key bindings. """ #--------------------------------------------------------------------------- # Trait definitions: #--------------------------------------------------------------------------- # Set of defined key bindings (added dynamically) #bindings = List( KeyBinding ) # Optional prefix to add to each method name prefix = Str # Optional suffix to add to each method name suffix = Str # Event fired when one of the contained KeyBinding objects is changed binding_modified = Event(KeyBinding) # Control that currently has the focus (if any) focus_owner = Any #--------------------------------------------------------------------------- # Traits view definitions: #--------------------------------------------------------------------------- traits_view = View([ Item('bindings@#', editor=ListEditor(style='custom')), '|{Click on a first or second column entry, then ' 'press the key to assign to the corresponding ' 'function}<>' ], title='Update Key Bindings', kind='livemodal', resizable=True, width=0.4, height=0.4, help=False) #--------------------------------------------------------------------------- # Initializes the object: #--------------------------------------------------------------------------- def __init__(self, *bindings, **traits): super(KeyBindings, self).__init__(**traits) n = len(bindings) self.add_trait('bindings', List(KeyBinding, minlen=n, maxlen=n, mode='list')) self.bindings = [binding.set(owner=self) for binding in bindings] #--------------------------------------------------------------------------- # Processes a keyboard event: #--------------------------------------------------------------------------- def do(self, event, controller, *args): """ Processes a keyboard event. """ key_name = toolkit().key_event_to_name(event) for binding in self.bindings: if (key_name == binding.binding1) or (key_name == binding.binding2): method_name = '%s%s%s' % (self.prefix, binding.method_name, self.suffix) return (getattr(controller, method_name)(*args) != False) return False #--------------------------------------------------------------------------- # Merges another set of key bindings into this set: #--------------------------------------------------------------------------- def merge(self, key_bindings): """ Merges another set of key bindings into this set. """ binding_dic = {} for binding in self.bindings: binding_dic[binding.method_name] = binding for binding in key_bindings.bindings: binding2 = binding_dic.get(binding.method_name) if binding2 is not None: binding2.binding1 = binding.binding1 binding2.binding2 = binding.binding2 #--------------------------------------------------------------------------- # Returns the current binding for a specified key (if any): #--------------------------------------------------------------------------- def key_binding_for(self, binding, key_name): """ Returns the current binding for a specified key (if any). """ if key_name != '': for a_binding in self.bindings: if ((a_binding is not binding) and ((key_name == a_binding.binding1) or (key_name == a_binding.binding2))): return a_binding return None #--------------------------------------------------------------------------- # Handles a binding being changed: #--------------------------------------------------------------------------- def _binding_modified_changed(self, binding): binding1 = binding.binding1 binding2 = binding.binding2 for a_binding in self.bindings: if binding is not a_binding: if binding1 == a_binding.binding1: a_binding.binding1 = '' if binding1 == a_binding.binding2: a_binding.binding2 = '' if binding2 == a_binding.binding1: a_binding.binding1 = '' if binding2 == a_binding.binding2: a_binding.binding2 = '' #--------------------------------------------------------------------------- # Handles the focus owner being changed: #--------------------------------------------------------------------------- def _focus_owner_changed(self, old, new): if old is not None: old.border_size = 0 #-- object overrides ----------------------------------------------------------- #--------------------------------------------------------------------------- # Restores the state of a previously pickled object: #--------------------------------------------------------------------------- def __setstate__(self, state): """ Restores the state of a previously pickled object. """ n = len(state['bindings']) self.add_trait('bindings', List(KeyBinding, minlen=n, maxlen=n)) self.__dict__.update(state) self.bindings = self.bindings[:]
salary = Int(label=u"薪水") bonus = Int(label=u"奖金") view = View("name", "department", "salary", "bonus") table_editor = TableEditor(columns=[ ObjectColumn(name="name", label=u"姓名"), ObjectColumn(name="department", label=u"部门"), ObjectColumn(name="salary", label=u"薪水"), ObjectColumn(name="bonus", label=u"奖金") ], row_factory=Employee, deletable=True, show_toolbar=True) list_editor = ListEditor(style="custom") tab_editor = ListEditor(use_notebook=True, deletable=True, page_name=".name") class EmployeeList(HasTraits): employees = List(Instance(Employee, factory=Employee)) view = View(HGroup(Item("employees", editor=table_editor), Item("employees", editor=list_editor), Item("employees", style="custom", editor=tab_editor), show_labels=False), resizable=True, width=600, title=u"列表编辑器演示") demo = EmployeeList()
class BoundaryMarkerEditor(Filter): """ Edit the boundary marker of a Triangle surface mesh. To use: select the label to assign, hover your cursor over the cell you wish to edit, and press 'p'. """ # The version of this class. Used for persistence. __version__ = 0 _current_grid = Instance(tvtk.UnstructuredGrid, allow_none=False) _input_grid = Instance(tvtk.UnstructuredGrid, args=(), allow_none=False) _extract_cells_filter = Instance(tvtk.ExtractCells, args=(), allow_none=False) _dataset_manager = Instance(DatasetManager, allow_none=False) _cell_mappings = List label_to_apply = Range(0, 255) select_coplanar_cells = Bool epsilon = Range(0.0, 1.0, 0.0001) mask_labels = Bool labels_to_mask = List(label_to_apply) # Saving file output_file = File save = Button ###################################################################### # The view. ###################################################################### traits_view = \ View( Group( Item(name='label_to_apply'), Item(name='select_coplanar_cells'), Item(name='epsilon', enabled_when='select_coplanar_cells', label='Tolerance'), Item(name='mask_labels'), Group( Item(name='labels_to_mask', style='custom', editor=ListEditor(rows=3)), show_labels=False, show_border=True, label='Labels to mask', enabled_when='mask_labels==True' ), Group( Item(name='output_file'), Item(name='save', label='Save'), show_labels=False, show_border=True, label='Save changes to file (give only a basename, without the file extension)' ) ), height=500, width=600 ) ###################################################################### # `Filter` interface. ###################################################################### def update_pipeline(self): if len(self.inputs) == 0 or len(self.inputs[0].outputs) == 0: return # Call cell_picked() when a cell is clicked. self.scene.picker.cellpicker.add_observer("EndPickEvent", self.cell_picked) self.scene.picker.pick_type = 'cell_picker' self.scene.picker.tolerance = 0.0 self.scene.picker.show_gui = False self._input_grid.deep_copy(self.inputs[0].outputs[0]) self._current_grid = self._input_grid self._dataset_manager = DatasetManager(dataset=self._input_grid) self._set_outputs([self._current_grid]) # Filter for masking. self._extract_cells_filter.set_input(self._input_grid) def update_data(self): self.data_changed = True ###################################################################### # Non-public interface. ###################################################################### def cell_picked(self, object, event): cell_id = self.scene.picker.cellpicker.cell_id self.modify_cell(cell_id, self.label_to_apply) if (self.select_coplanar_cells): self.modify_neighbouring_cells(cell_id) if (self.mask_labels): self.perform_mask() self._dataset_manager.activate(self._input_grid.cell_data.scalars.name, 'cell') self._dataset_manager.update() self.pipeline_changed = True def get_all_cell_neigbours(self, cell_id, cell): neighbour_cell_ids = array([], dtype=int) for i in range(cell.number_of_edges): # Get points belonging to ith edge edge_point_ids = cell.get_edge(i).point_ids # Find neigbours which share the edge current_neighbour_cell_ids = tvtk.IdList() self._current_grid.get_cell_neighbors(cell_id, edge_point_ids, current_neighbour_cell_ids) neighbour_cell_ids = append(neighbour_cell_ids, array(current_neighbour_cell_ids)) return neighbour_cell_ids.tolist() def modify_neighbouring_cells(self, cell_id): cell = self._current_grid.get_cell(cell_id) cell_normal = [0, 0, 0] cell.compute_normal(cell.points[0], cell.points[1], cell.points[2], cell_normal) cells_pending = self.get_all_cell_neigbours(cell_id, cell) cells_visited = [cell_id] while (len(cells_pending) > 0): current_cell_id = cells_pending.pop() if (current_cell_id not in cells_visited): cells_visited.append(current_cell_id) current_cell = self._current_grid.get_cell(current_cell_id) current_cell_normal = [0, 0, 0] current_cell.compute_normal(current_cell.points[0], current_cell.points[1], current_cell.points[2], current_cell_normal) if (dot(cell_normal, current_cell_normal) > (1 - self.epsilon)): self.modify_cell(current_cell_id, self.label_to_apply) cells_pending.extend( self.get_all_cell_neigbours(current_cell_id, current_cell)) def _mask_labels_changed(self): if (self.mask_labels): self.perform_mask() self._current_grid = self._extract_cells_filter.output else: self._current_grid = self._input_grid self._set_outputs([self._current_grid]) self.pipeline_changed = True def _labels_to_mask_changed(self): self.perform_mask() def _labels_to_mask_items_changed(self): self.perform_mask() def perform_mask(self): labels_array = self._input_grid.cell_data.get_array( self._input_grid.cell_data.scalars.name) in_masked = map(lambda x: x in self.labels_to_mask, labels_array) unmasked_cells_list = tvtk.IdList() cell_ids = range(self._input_grid.number_of_cells) # _cell_mappings is indexed by cell_id of the original input grid, and each value # is the new cell_id of the corresponding cell in the masked grid self._cell_mappings = map( lambda masked, cell_id: None if masked else unmasked_cells_list.insert_next_id(cell_id), in_masked, cell_ids) self._extract_cells_filter.set_cell_list(unmasked_cells_list) self._extract_cells_filter.update() self.pipeline_changed = True def modify_cell(self, cell_id, value): if (self.mask_labels): cell_id = self._cell_mappings.index( cell_id) # Adjust cell_id if masked self._input_grid.cell_data.get_array( self._input_grid.cell_data.scalars.name)[cell_id] = value def _save_fired(self): from mayavi_amcg.triangle_writer import TriangleWriter if (self.output_file): writer = TriangleWriter(self._input_grid, self.output_file) writer.write() print "#### Saved ####"
class MainWindow(HasTraits): parameter_file_collections = Instance(ParameterFileCollectionList) parameter_files = Instance(ParameterFileCollection) plot_frame_tabs = List(Instance(DataObject)) open_parameterfile = Button shell = PythonValue def _shell_default(self): return globals() notebook_editor = ListEditor(editor=InstanceEditor(editable=True), use_notebook=True) traits_view = View( VSplit( HSplit( VGroup( Item( 'parameter_file_collections', width=120.0, height=500.0, show_label=False, editor=TreeEditor( editable=False, nodes=[ TreeNode( node_for=[ParameterFileCollectionList], children='parameter_file_collections', label="=Data Collections"), TreeNode(node_for=[ParameterFileCollection], children='parameter_files', label="name", view=View()), TreeNode(node_for=[ParameterFile], children='data_objects', label="name", menu=Menu( Action(name='Slice', action='object.do_slice'), Action(name='Project', action='object.do_proj'), Action(name='VTK', action='object.do_vtk')), view=View()), TreeNode(node_for=[DataObject], children='', label="name"), ], show_icons=False), ), Item('open_parameterfile', show_label=False)), Item('plot_frame_tabs', style='custom', editor=notebook_editor, show_label=False, height=500.0, width=500.0), ), HGroup( #Item('shell', editor=ShellEditor(share=True), #show_label=False, height=120.0), ), ), resizable=True, width=800.0, height=660.0, title="reason v2 [prototype]") def _open_parameterfile_fired(self): print "OPENING" def _parameter_file_collections_default(self): return ParameterFileCollectionList()
class MultiFitGui(HasTraits): """ data should be c x N where c is the number of data columns/axes and N is the number of points """ doplot3d = Bool(False) show3d = Button('Show 3D Plot') replot3d = Button('Replot 3D') scalefactor3d = Float(0) do3dscale = Bool(False) nmodel3d = Int(1024) usecolor3d = Bool(False) color3d = Color((0,0,0)) scene3d = Instance(MlabSceneModel,()) plot3daxes = Tuple(('x','y','z')) data = Array(shape=(None,None)) weights = Array(shape=(None,)) curveaxes = List(Tuple(Int,Int)) axisnames = Dict(Int,Str) invaxisnames = Property(Dict,depends_on='axisnames') fgs = List(Instance(FitGui)) traits_view = View(VGroup(Item('fgs',editor=ListEditor(use_notebook=True,page_name='.plotname'),style='custom',show_label=False), Item('show3d',show_label=False)), resizable=True,height=900,buttons=['OK','Cancel'],title='Multiple Model Data Fitters') plot3d_view = View(VGroup(Item('scene3d',editor=SceneEditor(scene_class=MayaviScene),show_label=False,resizable=True), Item('plot3daxes',editor=TupleEditor(cols=3,labels=['x','y','z']),label='Axes'), HGroup(Item('do3dscale',label='Scale by weight?'), Item('scalefactor3d',label='Point scale'), Item('nmodel3d',label='Nmodel')), HGroup(Item('usecolor3d',label='Use color?'),Item('color3d',label='Relation Color',enabled_when='usecolor3d')), Item('replot3d',show_label=False),springy=True), resizable=True,height=800,width=800,title='Multiple Model3D Plot') def __init__(self,data,names=None,models=None,weights=None,dofits=True,**traits): """ :param data: The data arrays :type data: sequence of c equal-length arrays (length N) :param names: Names :type names: sequence of strings, length c :param models: The models to fit for each pair either as strings or :class:`astroypsics.models.ParametricModel` objects. :type models: sequence of models, length c-1 :param weights: the weights for each point or None for no weights :type weights: array-like of size N or None :param dofits: If True, the data will be fit to the models when the object is created, otherwise the models will be passed in as-is (or as created). :type dofits: bool extra keyword arguments get passed in as new traits (r[finmask],m[finmask],l[finmask]),names='rh,Mh,Lh',weights=w[finmask],models=models,dofits=False) """ super(MultiFitGui,self).__init__(**traits) self._lastcurveaxes = None data = np.array(data,copy=False) if weights is None: self.weights = np.ones(data.shape[1]) else: self.weights = np.array(weights) self.data = data if data.shape[0] < 2: raise ValueError('Must have at least 2 columns') if isinstance(names,basestring): names = names.split(',') if names is None: if len(data) == 2: self.axisnames = {0:'x',1:'y'} elif len(data) == 3: self.axisnames = {0:'x',1:'y',2:'z'} else: self.axisnames = dict((i,str(i)) for i in data) elif len(names) == len(data): self.axisnames = dict([t for t in enumerate(names)]) else: raise ValueError("names don't match data") #default to using 0th axis as parametric self.curveaxes = [(0,i) for i in range(len(data))[1:]] if models is not None: if len(models) != len(data)-1: raise ValueError("models don't match data") for i,m in enumerate(models): fg = self.fgs[i] newtmodel = TraitedModel(m) if dofits: fg.tmodel = newtmodel fg.fitmodel = True #should happen automatically, but this makes sure else: oldpard = newtmodel.model.pardict fg.tmodel = newtmodel fg.tmodel .model.pardict = oldpard if dofits: fg.fitmodel = True def _data_changed(self): self.curveaxes = [(0,i) for i in range(len(self.data))[1:]] def _axisnames_changed(self): for ax,fg in zip(self.curveaxes,self.fgs): fg.plot.x_axis.title = self.axisnames[ax[0]] if ax[0] in self.axisnames else '' fg.plot.y_axis.title = self.axisnames[ax[1]] if ax[1] in self.axisnames else '' self.plot3daxes = (self.axisnames[0],self.axisnames[1],self.axisnames[2] if len(self.axisnames) > 2 else self.axisnames[1]) @on_trait_change('curveaxes[]') def _curveaxes_update(self,names,old,new): ax=[] for t in self.curveaxes: ax.append(t[0]) ax.append(t[1]) if set(ax) != set(range(len(self.data))): self.curveaxes = self._lastcurveaxes return #TOOD:check for recursion if self._lastcurveaxes is None: self.fgs = [FitGui(self.data[t[0]],self.data[t[1]],weights=self.weights) for t in self.curveaxes] for ax,fg in zip(self.curveaxes,self.fgs): fg.plot.x_axis.title = self.axisnames[ax[0]] if ax[0] in self.axisnames else '' fg.plot.y_axis.title = self.axisnames[ax[1]] if ax[1] in self.axisnames else '' else: for i,t in enumerate(self.curveaxes): if self._lastcurveaxes[i] != t: self.fgs[i] = fg = FitGui(self.data[t[0]],self.data[t[1]],weights=self.weights) ax = self.curveaxes[i] fg.plot.x_axis.title = self.axisnames[ax[0]] if ax[0] in self.axisnames else '' fg.plot.y_axis.title = self.axisnames[ax[1]] if ax[1] in self.axisnames else '' self._lastcurveaxes = self.curveaxes def _show3d_fired(self): self.edit_traits(view='plot3d_view') self.doplot3d = True self.replot3d = True def _plot3daxes_changed(self): self.replot3d = True @on_trait_change('weights',post_init=True) def weightsChanged(self): for fg in self.fgs: if fg.weighttype != 'custom': fg.weighttype = 'custom' fg.weights = self.weights @on_trait_change('data','fgs','replot3d','weights') def _do_3d(self): if self.doplot3d: M = self.scene3d.mlab try: xi = self.invaxisnames[self.plot3daxes[0]] yi = self.invaxisnames[self.plot3daxes[1]] zi = self.invaxisnames[self.plot3daxes[2]] x,y,z = self.data[xi],self.data[yi],self.data[zi] w = self.weights M.clf() if self.scalefactor3d == 0: sf = x.max()-x.min() sf *= y.max()-y.min() sf *= z.max()-z.min() sf = sf/len(x)/5 self.scalefactor3d = sf else: sf = self.scalefactor3d glyph = M.points3d(x,y,z,w,scale_factor=sf) glyph.glyph.scale_mode = 0 if self.do3dscale else 1 M.axes(xlabel=self.plot3daxes[0],ylabel=self.plot3daxes[1],zlabel=self.plot3daxes[2]) try: xs = np.linspace(np.min(x),np.max(x),self.nmodel3d) #find sequence of models to go from x to y and z ymods,zmods = [],[] for curri,mods in zip((yi,zi),(ymods,zmods)): while curri != xi: for i,(i1,i2) in enumerate(self.curveaxes): if curri==i2: curri = i1 mods.insert(0,self.fgs[i].tmodel.model) break else: raise KeyError ys = xs for m in ymods: ys = m(ys) zs = xs for m in zmods: zs = m(zs) if self.usecolor3d: c = (self.color3d[0]/255,self.color3d[1]/255,self.color3d[2]/255) M.plot3d(xs,ys,zs,color=c) else: M.plot3d(xs,ys,zs,np.arange(len(xs))) except (KeyError,TypeError): M.text(0.5,0.75,'Underivable relation') except KeyError: M.clf() M.text(0.25,0.25,'Data problem') @cached_property def _get_invaxisnames(self): d={} for k,v in self.axisnames.iteritems(): d[v] = k return d
class MultiSelections(HasTraits): """ Object used to store analysis objects in List of points """ selections = List(RectangleSelection) selection = Instance(RectangleSelection, transient=True) #: default filename for points load, save filename = File() add_point = Button() load = Button() save = Button() index_high = Property(Int, depends_on='selections', transient=True) index = Property(Int, depends_on='selection,index_high', transient=True) updated = Event() _update = Bool(True) view = View(Item('index', editor=RangeEditor(low=0, high_name='index_high', is_float=False, mode='spinner')), HGroup( Item('add_point', show_label=False, springy=True), Item('load', show_label=False, springy=True), Item('save', show_label=False, springy=True), ), '_', VGroup( Item('selections@', id='notebook', show_label=False, editor=ListEditor(use_notebook=True, deletable=True, selected='selection', export='DockWindowShell', page_name='.name')), ), id='enthought.traits.ui.demo.Traits UI Demo.Advanced.' 'List_editor_notebook_selection_demo', dock='horizontal', resizable=True, height=-0.5) def _load_fired(self): f = FileDialog(action='open', title='Load points', default_path=self.filename, wildcard='*.points') if f.open() == OK: self.filename = f.path self.from_file() def _save_fired(self): f = FileDialog(action='save as', title='Save points', default_path=self.filename, wildcard='*.points') if f.open() == OK: self.filename = f.path self.to_file() def _selection_default(self): return self.selections[0] def _get_index_high(self): return len(self.selections) - 1 def _add_point_fired(self): self._update = False point = (self.selections[self.index]).clone_traits() point.name = 'point ' + str(len(self.selections)) self.selections.append(point) self.selection = self.selections[-1] self._update = True self.update() def _selections_default(self): return POINTS @on_trait_change('selections[]') def _update_names(self): #update point names for i, point in enumerate(self.selections): point.name = 'point ' + str(i) def _get_index(self): try: return self.selections.index(self.selection) except: return self.index_high self.update() def _set_index(self, value): self.selection = self.selections[value] def from_file(self): """Reads selections from file """ with open(self.filename, 'rb') as f: self._update = False self.selections = pickle.load(f) self.index = 0 self._update = True self.update() def to_file(self): """Stores selections to file """ with open(self.filename, 'wb') as f: pickle.dump(self.selections, f) @on_trait_change('selection.updated') def update(self): """ Notify update """ if self._update: self.updated = True