Changeset 8722:32e7a9d98231 in orange


Ignore:
Timestamp:
08/17/11 18:35:20 (3 years ago)
Author:
matejd <matejd@…>
Branch:
default
Convert:
75aea6f80d8564d17dd80ddc75cf5e7ef8448df8
Message:

Removed old code from prototypes

Location:
orange/OrangeWidgets/Visualize Qt
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/Visualize Qt/OWRadviz3D.py

    r8687 r8722  
    11""" 
    2 <name>Sphereviz 3D</name> 
     2<name>RadViz 3D</name> 
    33<icon>icons/Radviz.png</icon> 
    4 <priority>320</priority> 
     4<priority>2000</priority> 
    55""" 
    66 
     
    1313 
    1414class OWRadviz3DPlot(OWPlot3D, orngScaleLinProjData3D): 
    15     def __init__(self, widget, parent=None, name='Sphereviz 3D'): 
     15    def __init__(self, widget, parent=None, name='None'): 
    1616        OWPlot3D.__init__(self, parent) 
    1717        orngScaleLinProjData3D.__init__(self) 
  • orange/OrangeWidgets/Visualize Qt/OWScatterPlot3D.py

    r8687 r8722  
    1 """<name>Scatterplot 3D</name> 
    2 <description></description> 
    3 <icon></icon> 
    4 <contact></contact> 
    5 <priority>310</priority> 
    6 """ 
     1'''<name>Scatterplot 3D</name> 
     2''' 
    73 
    84from OWWidget import * 
     
    1511import OWGUI 
    1612import OWToolbars 
    17 import OWColorPalette 
    1813import orngVizRank 
    1914from OWkNNOptimization import * 
     
    2318 
    2419TooltipKind = enum('NONE', 'VISIBLE', 'ALL') # Which attributes should be displayed in tooltips? 
     20 
     21class ScatterPlotTheme(PlotTheme): 
     22    def __init__(self): 
     23        super(ScatterPlotTheme, self).__init__() 
     24        self.grid_color = [0.8, 0.8, 0.8, 1.] 
     25 
     26class LightTheme(ScatterPlotTheme): 
     27    pass 
     28 
     29class DarkTheme(ScatterPlotTheme): 
     30    def __init__(self): 
     31        super(DarkTheme, self).__init__() 
     32        self.grid_color = [0.3, 0.3, 0.3, 1.] 
     33        self.labels_color = [0.9, 0.9, 0.9, 1.] 
     34        self.helpers_color = [0.9, 0.9, 0.9, 1.] 
     35        self.axis_values_color = [0.7, 0.7, 0.7, 1.] 
     36        self.axis_color = [0.8, 0.8, 0.8, 1.] 
     37        self.background_color = [0., 0., 0., 1.] 
    2538 
    2639class ScatterPlot(OWPlot3D, orngScaleScatterPlotData): 
     
    2942        orngScaleScatterPlotData.__init__(self) 
    3043 
    31     def set_data(self, data, subsetData=None, **args): 
    32         orngScaleScatterPlotData.setData(self, data, subsetData, **args) 
     44        self.disc_palette = ColorPaletteGenerator() 
     45        self._theme = LightTheme() 
     46        self.show_grid = True 
     47        self.show_chassis = True 
     48 
     49    def set_data(self, data, subset_data=None, **args): 
     50        orngScaleScatterPlotData.set_data(self, data, subset_data, **args) 
     51        OWPlot3D.set_data(self, self.no_jittering_scaled_data, self.no_jittering_scaled_subset_data) 
     52        # TODO: wire jitter settings (actual jittering done in geometry shader) 
     53 
     54    def update_data(self, x_attr, y_attr, z_attr, 
     55                    color_attr, symbol_attr, size_attr, label_attr): 
     56        self.before_draw_callback = self.before_draw 
     57 
     58        color_discrete = symbol_discrete = size_discrete = False 
     59 
     60        color_index = -1 
     61        if color_attr != '' and color_attr != '(Same color)': 
     62            color_index = self.attribute_name_index[color_attr] 
     63            if self.data_domain[color_attr].varType == Discrete: 
     64                color_discrete = True 
     65                self.disc_palette.setNumberOfColors(len(self.data_domain[color_attr].values)) 
     66 
     67        symbol_index = -1 
     68        num_symbols_used = -1 
     69        if symbol_attr != '' and symbol_attr != 'Same symbol)' and\ 
     70           len(self.data_domain[symbol_attr].values) < len(Symbol): 
     71            symbol_index = self.attribute_name_index[symbol_attr] 
     72            if self.data_domain[symbol_attr].varType == Discrete: 
     73                symbol_discrete = True 
     74                num_symbols_used = len(self.data_domain[symbol_attr].values) 
     75 
     76        size_index = -1 
     77        if size_attr != '' and size_attr != '(Same size)': 
     78            size_index = self.attribute_name_index[size_attr] 
     79            if self.data_domain[size_attr].varType == Discrete: 
     80                size_discrete = True 
     81 
     82        label_index = -1 
     83        if label_attr != '' and label_attr != '(No labels)': 
     84            label_index = self.attribute_name_index[label_attr] 
     85 
     86        x_index = self.attribute_name_index[x_attr] 
     87        y_index = self.attribute_name_index[y_attr] 
     88        z_index = self.attribute_name_index[z_attr] 
     89 
     90        x_discrete = self.data_domain[x_attr].varType == Discrete 
     91        y_discrete = self.data_domain[y_attr].varType == Discrete 
     92        z_discrete = self.data_domain[z_attr].varType == Discrete 
     93 
     94        colors = [] 
     95        if color_discrete: 
     96            for i in range(len(self.data_domain[color_attr].values)): 
     97                c = self.disc_palette[i] 
     98                colors.append([c.red()/255., c.green()/255., c.blue()/255.]) 
     99 
     100        data_scale = [self.attr_values[x_attr][1] - self.attr_values[x_attr][0], 
     101                      self.attr_values[y_attr][1] - self.attr_values[y_attr][0], 
     102                      self.attr_values[z_attr][1] - self.attr_values[z_attr][0]] 
     103        data_translation = [self.attr_values[x_attr][0], 
     104                            self.attr_values[y_attr][0], 
     105                            self.attr_values[z_attr][0]] 
     106        data_scale = 1. / numpy.array(data_scale) 
     107        if x_discrete: 
     108            data_scale[0] = 0.5 / float(len(self.data_domain[x_attr].values)) 
     109            data_translation[0] = 1. 
     110        if y_discrete: 
     111            data_scale[1] = 0.5 / float(len(self.data_domain[y_attr].values)) 
     112            data_translation[1] = 1. 
     113        if z_discrete: 
     114            data_scale[2] = 0.5 / float(len(self.data_domain[z_attr].values)) 
     115            data_translation[2] = 1. 
     116 
     117        self.clear() 
     118        self.set_shown_attributes_indices(x_index, y_index, z_index, 
     119            color_index, symbol_index, size_index, label_index, 
     120            colors, num_symbols_used, data_scale, data_translation) 
     121 
     122        if self.show_legend: 
     123            legend_keys = {} 
     124            color_index = color_index if color_index != -1 and color_discrete else -1 
     125            size_index = size_index if size_index != -1 and size_discrete else -1 
     126            symbol_index = symbol_index if symbol_index != -1 and symbol_discrete else -1 
     127 
     128            single_legend = [color_index, size_index, symbol_index].count(-1) == 2 
     129            if single_legend: 
     130                legend_join = lambda name, val: val 
     131            else: 
     132                legend_join = lambda name, val: name + '=' + val  
     133 
     134            color_attr = self.data_domain[color_attr] if color_index != -1 else None 
     135            symbol_attr = self.data_domain[symbol_attr] if symbol_index != -1 else None 
     136            size_attr = self.data_domain[size_attr] if size_index != -1 else None 
     137 
     138            if color_index != -1: 
     139                num = len(color_attr.values) 
     140                val = [[], [], [1.]*num, [Symbol.RECT]*num] 
     141                var_values = get_variable_values_sorted(color_attr) 
     142                for i in range(num): 
     143                    val[0].append(legend_join(color_attr.name, var_values[i])) 
     144                    c = self.disc_palette[i] 
     145                    val[1].append([c.red()/255., c.green()/255., c.blue()/255., 1.]) 
     146                legend_keys[color_attr] = val 
     147 
     148            if symbol_index != -1: 
     149                num = len(symbol_attr.values) 
     150                if legend_keys.has_key(symbol_attr): 
     151                    val = legend_keys[symbol_attr] 
     152                else: 
     153                    val = [[], [(0, 0, 0, 1)]*num, [1.]*num, []] 
     154                var_values = get_variable_values_sorted(symbol_attr) 
     155                val[3] = [] 
     156                val[0] = [] 
     157                for i in range(num): 
     158                    val[3].append(i) 
     159                    val[0].append(legend_join(symbol_attr.name, var_values[i])) 
     160                legend_keys[symbol_attr] = val 
     161 
     162            if size_index != -1: 
     163                num = len(size_attr.values) 
     164                if legend_keys.has_key(size_attr): 
     165                    val = legend_keys[size_attr] 
     166                else: 
     167                    val = [[], [(0, 0, 0, 1)]*num, [], [Symbol.RECT]*num] 
     168                val[2] = [] 
     169                val[0] = [] 
     170                var_values = get_variable_values_sorted(size_attr) 
     171                for i in range(num): 
     172                    val[0].append(legend_join(size_attr.name, var_values[i])) 
     173                    val[2].append(0.1 + float(i) / len(var_values)) 
     174                legend_keys[size_attr] = val 
     175 
     176            for val in legend_keys.values(): 
     177                for i in range(len(val[1])): 
     178                    self.legend.add_item(val[3][i], val[1][i], val[2][i], val[0][i]) 
     179 
     180        self.set_axis_title(Axis.X, x_attr) 
     181        self.set_axis_title(Axis.Y, y_attr) 
     182        self.set_axis_title(Axis.Z, z_attr) 
     183 
     184        if x_discrete: 
     185            self.set_axis_labels(Axis.X, get_variable_values_sorted(self.data_domain[x_attr])) 
     186        if y_discrete: 
     187            self.set_axis_labels(Axis.Y, get_variable_values_sorted(self.data_domain[y_attr])) 
     188        if z_discrete: 
     189            self.set_axis_labels(Axis.Z, get_variable_values_sorted(self.data_domain[z_attr])) 
     190 
     191        self.updateGL() 
     192 
     193    def before_draw(self): 
     194        glMatrixMode(GL_PROJECTION) 
     195        glLoadIdentity() 
     196        glMultMatrixd(numpy.array(self.projection.data(), dtype=float)) 
     197        glMatrixMode(GL_MODELVIEW) 
     198        glLoadIdentity() 
     199        glMultMatrixd(numpy.array(self.modelview.data(), dtype=float)) 
     200 
     201        if self.show_grid: 
     202            self.draw_grid() 
     203        if self.show_chassis: 
     204            self.draw_chassis() 
     205 
     206    def draw_chassis(self): 
     207        glColor4f(*self._theme.axis_values_color) 
     208        glEnable(GL_LINE_STIPPLE) 
     209        glLineStipple(1, 0x00FF) 
     210        glDisable(GL_DEPTH_TEST) 
     211        glLineWidth(1) 
     212        glEnable(GL_BLEND) 
     213        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
     214        edges = [self.x_axis, self.y_axis, self.z_axis, 
     215                 self.x_axis+self.unit_z, self.x_axis+self.unit_y, 
     216                 self.x_axis+self.unit_z+self.unit_y, 
     217                 self.y_axis+self.unit_x, self.y_axis+self.unit_z, 
     218                 self.y_axis+self.unit_x+self.unit_z, 
     219                 self.z_axis+self.unit_x, self.z_axis+self.unit_y, 
     220                 self.z_axis+self.unit_x+self.unit_y] 
     221        glBegin(GL_LINES) 
     222        for edge in edges: 
     223            start, end = edge 
     224            glVertex3f(*start) 
     225            glVertex3f(*end) 
     226        glEnd() 
     227        glDisable(GL_LINE_STIPPLE) 
     228        glEnable(GL_DEPTH_TEST) 
     229        glDisable(GL_BLEND) 
     230 
     231    def draw_grid(self): 
     232        cam_in_space = numpy.array([ 
     233          self.camera[0]*self.camera_distance, 
     234          self.camera[1]*self.camera_distance, 
     235          self.camera[2]*self.camera_distance 
     236        ]) 
     237 
     238        def _draw_grid(axis0, axis1, normal0, normal1, i, j): 
     239            glColor4f(*self._theme.grid_color) 
     240            for axis, normal, coord_index in zip([axis0, axis1], [normal0, normal1], [i, j]): 
     241                start, end = axis.copy() 
     242                start_value = self.map_to_data(start.copy())[coord_index] 
     243                end_value = self.map_to_data(end.copy())[coord_index] 
     244                values, _ = loose_label(start_value, end_value, 7) 
     245                for value in values: 
     246                    if not (start_value <= value <= end_value): 
     247                        continue 
     248                    position = start + (end-start)*((value-start_value) / float(end_value-start_value)) 
     249                    glBegin(GL_LINES) 
     250                    glVertex3f(*position) 
     251                    glVertex3f(*(position-normal*1.)) 
     252                    glEnd() 
     253 
     254        glDisable(GL_DEPTH_TEST) 
     255        glLineWidth(1) 
     256        glEnable(GL_BLEND) 
     257        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 
     258 
     259        planes = [self.axis_plane_xy, self.axis_plane_yz, 
     260                  self.axis_plane_xy_back, self.axis_plane_yz_right] 
     261        axes = [[self.x_axis, self.y_axis], 
     262                [self.y_axis, self.z_axis], 
     263                [self.x_axis+self.unit_z, self.y_axis+self.unit_z], 
     264                [self.z_axis+self.unit_x, self.y_axis+self.unit_x]] 
     265        normals = [[numpy.array([0,-1, 0]), numpy.array([-1, 0, 0])], 
     266                   [numpy.array([0, 0,-1]), numpy.array([ 0,-1, 0])], 
     267                   [numpy.array([0,-1, 0]), numpy.array([-1, 0, 0])], 
     268                   [numpy.array([0,-1, 0]), numpy.array([ 0, 0,-1])]] 
     269        coords = [[0, 1], 
     270                  [1, 2], 
     271                  [0, 1], 
     272                  [2, 1]] 
     273        visible_planes = [plane_visible(plane, cam_in_space) for plane in planes] 
     274        xz_visible = not plane_visible(self.axis_plane_xz, cam_in_space) 
     275        if xz_visible: 
     276            _draw_grid(self.x_axis, self.z_axis, numpy.array([0,0,-1]), numpy.array([-1,0,0]), 0, 2) 
     277        for visible, (axis0, axis1), (normal0, normal1), (i, j) in\ 
     278             zip(visible_planes, axes, normals, coords): 
     279            if not visible: 
     280                _draw_grid(axis0, axis1, normal0, normal1, i, j) 
     281 
     282        glEnable(GL_DEPTH_TEST) 
     283        glDisable(GL_BLEND) 
    33284 
    34285class OWScatterPlot3D(OWWidget): 
     
    38289                    'plot.show_chassis', 'plot.show_axes', 
    39290                    'auto_send_selection', 'auto_send_selection_update', 
    40                     'jitter_size', 'jitter_continuous'] 
    41     contextHandlers = {"": DomainContextHandler("", ["x_attr", "y_attr", "z_attr"])} 
     291                    'plot.jitter_size', 'plot.jitter_continuous'] 
     292    contextHandlers = {'': DomainContextHandler('', ['x_attr', 'y_attr', 'z_attr'])} 
    42293    jitter_sizes = [0.0, 0.1, 0.5, 1, 2, 3, 4, 5, 7, 10, 15, 20, 30, 40, 50] 
    43294 
    44     def __init__(self, parent=None, signalManager=None, name="Scatterplot 3D"): 
     295    def __init__(self, parent=None, signalManager=None, name='Scatter Plot 3D'): 
    45296        OWWidget.__init__(self, parent, signalManager, name, True) 
    46297 
    47         self.inputs = [("Examples", ExampleTable, self.set_data, Default), ("Subset Examples", ExampleTable, self.set_subset_data)] 
    48         self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable)] 
    49  
    50         self.x_attr = 0 
    51         self.y_attr = 0 
    52         self.z_attr = 0 
     298        self.inputs = [('Examples', ExampleTable, self.set_data, Default), ('Subset Examples', ExampleTable, self.set_subset_data)] 
     299        self.outputs = [('Selected Examples', ExampleTable), ('Unselected Examples', ExampleTable)] 
     300 
     301        self.x_attr = '' 
     302        self.y_attr = '' 
     303        self.z_attr = '' 
    53304 
    54305        self.x_attr_discrete = False 
     
    56307        self.z_attr_discrete = False 
    57308 
    58         self.color_attr = None 
    59         self.size_attr = None 
    60         self.shape_attr = None 
    61         self.label_attr = None 
    62  
    63         self.alpha_value = 255 
     309        self.color_attr = '' 
     310        self.size_attr = '' 
     311        self.symbol_attr = '' 
     312        self.label_attr = '' 
    64313 
    65314        self.tabs = OWGUI.tabWidget(self.controlArea) 
     
    67316        self.settings_tab = OWGUI.createTabPage(self.tabs, 'Settings', canScroll=True) 
    68317 
    69         self.x_attr_cb = OWGUI.comboBox(self.main_tab, self, "x_attr", box="X-axis attribute", 
    70             tooltip="Attribute to plot on X axis.", 
    71             callback=self.on_axis_change 
    72             ) 
    73  
    74         self.y_attr_cb = OWGUI.comboBox(self.main_tab, self, "y_attr", box="Y-axis attribute", 
    75             tooltip="Attribute to plot on Y axis.", 
    76             callback=self.on_axis_change 
    77             ) 
    78  
    79         self.z_attr_cb = OWGUI.comboBox(self.main_tab, self, "z_attr", box="Z-axis attribute", 
    80             tooltip="Attribute to plot on Z axis.", 
    81             callback=self.on_axis_change 
    82             ) 
    83  
    84         self.color_attr_cb = OWGUI.comboBox(self.main_tab, self, "color_attr", box="Point color", 
    85             tooltip="Attribute to use for point color", 
    86             callback=self.on_axis_change) 
    87  
    88         # Additional point properties (labels, size, shape). 
     318        self.x_attr_cb = OWGUI.comboBox(self.main_tab, self, 'x_attr', box='X-axis attribute', 
     319            tooltip='Attribute to plot on X axis.', 
     320            callback=self.on_axis_change, 
     321            sendSelectedValue=1, 
     322            valueType=str) 
     323 
     324        self.y_attr_cb = OWGUI.comboBox(self.main_tab, self, 'y_attr', box='Y-axis attribute', 
     325            tooltip='Attribute to plot on Y axis.', 
     326            callback=self.on_axis_change, 
     327            sendSelectedValue=1, 
     328            valueType=str) 
     329 
     330        self.z_attr_cb = OWGUI.comboBox(self.main_tab, self, 'z_attr', box='Z-axis attribute', 
     331            tooltip='Attribute to plot on Z axis.', 
     332            callback=self.on_axis_change, 
     333            sendSelectedValue=1, 
     334            valueType=str) 
     335 
     336        self.color_attr_cb = OWGUI.comboBox(self.main_tab, self, 'color_attr', box='Point color', 
     337            tooltip='Attribute to use for point color', 
     338            callback=self.on_axis_change, 
     339            sendSelectedValue=1, 
     340            valueType=str) 
     341 
     342        # Additional point properties (labels, size, symbol). 
    89343        additional_box = OWGUI.widgetBox(self.main_tab, 'Additional Point Properties') 
    90         self.size_attr_cb = OWGUI.comboBox(additional_box, self, "size_attr", label="Point size:", 
    91             tooltip="Attribute to use for pointSize", 
     344        self.size_attr_cb = OWGUI.comboBox(additional_box, self, 'size_attr', label='Point size:', 
     345            tooltip='Attribute to use for point size', 
    92346            callback=self.on_axis_change, 
    93347            indent=10, 
    94348            emptyString='(Same size)', 
    95             ) 
    96  
    97         self.shape_attr_cb = OWGUI.comboBox(additional_box, self, "shape_attr", label="Point shape:", 
    98             tooltip="Attribute to use for pointShape", 
     349            sendSelectedValue=1, 
     350            valueType=str) 
     351 
     352        self.symbol_attr_cb = OWGUI.comboBox(additional_box, self, 'symbol_attr', label='Point symbol:', 
     353            tooltip='Attribute to use for point symbol', 
    99354            callback=self.on_axis_change, 
    100355            indent=10, 
    101             emptyString='(Same shape)', 
    102             ) 
    103  
    104         self.label_attr_cb = OWGUI.comboBox(additional_box, self, "label_attr", label="Point label:", 
    105             tooltip="Attribute to use for pointLabel", 
     356            emptyString='(Same symbol)', 
     357            sendSelectedValue=1, 
     358            valueType=str) 
     359 
     360        self.label_attr_cb = OWGUI.comboBox(additional_box, self, 'label_attr', label='Point label:', 
     361            tooltip='Attribute to use for pointLabel', 
    106362            callback=self.on_axis_change, 
    107363            indent=10, 
    108             emptyString='(No labels)' 
    109             ) 
     364            emptyString='(No labels)', 
     365            sendSelectedValue=1, 
     366            valueType=str) 
    110367 
    111368        self.plot = ScatterPlot(self) 
    112         self.vizrank = OWVizRank(self, self.signalManager, self.plot, orngVizRank.SCATTERPLOT3D, "ScatterPlot3D") 
     369        self.vizrank = OWVizRank(self, self.signalManager, self.plot, orngVizRank.SCATTERPLOT3D, 'ScatterPlot3D') 
    113370        self.optimization_dlg = self.vizrank 
    114371 
    115372        self.optimization_buttons = OWGUI.widgetBox(self.main_tab, 'Optimization dialogs', orientation='horizontal') 
    116         OWGUI.button(self.optimization_buttons, self, "VizRank", callback=self.vizrank.reshow, 
     373        OWGUI.button(self.optimization_buttons, self, 'VizRank', callback=self.vizrank.reshow, 
    117374            tooltip='Opens VizRank dialog, where you can search for interesting projections with different subsets of attributes', 
    118375            debuggingEnabled=0) 
    119376 
    120377        box = OWGUI.widgetBox(self.settings_tab, 'Point properties') 
    121         ss = OWGUI.hSlider(box, self, "plot.symbol_scale", label="Symbol scale", 
    122             minValue=1, maxValue=20, 
    123             tooltip="Scale symbol size", 
    124             callback=self.on_checkbox_update, 
    125             ) 
    126         ss.setValue(5) 
    127  
    128         OWGUI.hSlider(box, self, "plot.transparency", label="Transparency", 
     378        ss = OWGUI.hSlider(box, self, 'plot.symbol_scale', label='Symbol scale', 
     379            minValue=0, maxValue=20, 
     380            tooltip='Scale symbol size', 
     381            callback=self.on_checkbox_update) 
     382        ss.setValue(4) 
     383 
     384        OWGUI.hSlider(box, self, 'plot.transparency', label='Transparency', 
    129385            minValue=10, maxValue=255, 
    130             tooltip="Point transparency value", 
     386            tooltip='Point transparency value', 
    131387            callback=self.on_checkbox_update) 
    132388        OWGUI.rubber(box) 
    133389 
    134         self.jitter_size = 0 
    135         self.jitter_continuous = False 
    136         box = OWGUI.widgetBox(self.settings_tab, "Jittering Options") 
    137         self.jitter_size_combo = OWGUI.comboBox(box, self, 'jitter_size', label='Jittering size (% of size)'+'  ', 
     390        box = OWGUI.widgetBox(self.settings_tab, 'Jittering Options') 
     391        self.jitter_size_combo = OWGUI.comboBox(box, self, 'plot.jitter_size', label='Jittering size (% of size)'+'  ', 
    138392            orientation='horizontal', 
    139393            callback=self.update_plot, 
     
    141395            sendSelectedValue=1, 
    142396            valueType=float) 
    143         OWGUI.checkBox(box, self, 'jitter_continuous', 'Jitter continuous attributes', 
     397        OWGUI.checkBox(box, self, 'plot.jitter_continuous', 'Jitter continuous attributes', 
    144398            callback=self.update_plot, 
    145399            tooltip='Does jittering apply also on continuous attributes?') 
     
    153407        OWGUI.checkBox(box, self, 'plot.show_legend',         'Show legend',    callback=self.on_checkbox_update) 
    154408        OWGUI.checkBox(box, self, 'plot.use_ortho',           'Use ortho',      callback=self.on_checkbox_update) 
    155         OWGUI.checkBox(box, self, 'plot.use_2d_symbols',      '2D symbols',     callback=self.on_checkbox_update) 
     409        OWGUI.checkBox(box, self, 'plot.use_2d_symbols',      '2D symbols',     callback=self.update_plot) 
    156410        OWGUI.checkBox(box, self, 'dark_theme',               'Dark theme',     callback=self.on_theme_change) 
    157411        OWGUI.checkBox(box, self, 'plot.show_grid',           'Show grid',      callback=self.on_checkbox_update) 
    158412        OWGUI.checkBox(box, self, 'plot.show_axes',           'Show axes',      callback=self.on_checkbox_update) 
    159413        OWGUI.checkBox(box, self, 'plot.show_chassis',        'Show chassis',   callback=self.on_checkbox_update) 
    160         OWGUI.checkBox(box, self, 'plot.draw_point_cloud',    'Point cloud',    callback=self.on_checkbox_update) 
    161414        OWGUI.checkBox(box, self, 'plot.hide_outside',        'Hide outside',   callback=self.on_checkbox_update) 
    162415        OWGUI.rubber(box) 
     
    183436 
    184437        self.tooltip_kind = TooltipKind.NONE 
    185         box = OWGUI.widgetBox(self.settings_tab, "Tooltips Settings") 
     438        box = OWGUI.widgetBox(self.settings_tab, 'Tooltips Settings') 
    186439        OWGUI.comboBox(box, self, 'tooltip_kind', items = [ 
    187440            'Don\'t Show Tooltips', 'Show Visible Attributes', 'Show All Attributes']) 
    188441 
    189442        self.plot.mouseover_callback = self.mouseover_callback 
    190         self.shown_attr_indices = [] 
    191443 
    192444        self.main_tab.layout().addStretch(100) 
     
    194446 
    195447        self.mainArea.layout().addWidget(self.plot) 
    196         self.connect(self.graphButton, SIGNAL("clicked()"), self.plot.save_to_file) 
     448        self.connect(self.graphButton, SIGNAL('clicked()'), self.plot.save_to_file) 
    197449 
    198450        self.loadSettings() 
     
    200452 
    201453        self.data = None 
    202         self.subsetData = None 
    203         self.data_array_jittered = None 
     454        self.subset_data = None 
    204455        self.resize(1100, 600) 
    205456 
     
    212463    def get_example_tooltip(self, example, indices=None, max_indices=20): 
    213464        if indices and type(indices[0]) == str: 
    214             indices = [self.attr_name_index[i] for i in indices] 
     465            indices = [self.plot.attribute_name_index[i] for i in indices] 
    215466        if not indices: 
    216467            indices = range(len(self.data.domain.attributes)) 
    217468 
    218469        if example.domain.classVar: 
    219             classIndex = self.attr_name_index[example.domain.classVar.name] 
     470            classIndex = self.plot.attribute_name_index[example.domain.classVar.name] 
    220471            while classIndex in indices: 
    221472                indices.remove(classIndex) 
     
    223474        text = '<b>Attributes:</b><br>' 
    224475        for index in indices[:max_indices]: 
    225             attr = self.attr_name[index] 
     476            attr = self.attribute_names[index] 
    226477            if attr not in example.domain:  text += '&nbsp;'*4 + '%s = ?<br>' % (attr) 
    227478            elif example[attr].isSpecial(): text += '&nbsp;'*4 + '%s = ?<br>' % (attr) 
     
    251502                self.plot.remove_all_selections() 
    252503                return 
    253             # TODO: refactor this properly 
    254             if self.data_array_jittered: 
    255                 X, Y, Z = self.data_array_jittered 
    256             else: 
    257                 X, Y, Z = self.data_array[:, self.x_attr],\ 
    258                           self.data_array[:, self.y_attr],\ 
    259                           self.data_array[:, self.z_attr] 
    260             X = [X[i] for i in indices] 
    261             Y = [Y[i] for i in indices] 
    262             Z = [Z[i] for i in indices] 
    263             min_x, max_x = numpy.min(X), numpy.max(X) 
    264             min_y, max_y = numpy.min(Y), numpy.max(Y) 
    265             min_z, max_z = numpy.min(Z), numpy.max(Z) 
    266             self.plot.set_new_zoom(min_x, max_x, min_y, max_y, min_z, max_z) 
     504            selected_indices = [1 if i in indices else 0 
     505                                for i in range(len(self.data))] 
     506            selected = self.plot.rawData.selectref(selected_indices) 
     507            x_min = y_min = z_min = 1e100 
     508            x_max = y_max = z_max = -1e100 
     509            x_index = self.plot.attribute_name_index[self.x_attr] 
     510            y_index = self.plot.attribute_name_index[self.y_attr] 
     511            z_index = self.plot.attribute_name_index[self.z_attr] 
     512            # TODO: there has to be a faster way 
     513            for example in selected: 
     514                x_min = min(example[x_index], x_min) 
     515                y_min = min(example[y_index], y_min) 
     516                z_min = min(example[z_index], z_min) 
     517                x_max = max(example[x_index], x_max) 
     518                y_max = max(example[y_index], y_max) 
     519                z_max = max(example[z_index], z_max) 
     520            self.plot.set_new_zoom(x_min, x_max, y_min, y_max, z_min, z_max) 
    267521        else: 
    268522            if self.auto_send_selection: 
    269                 self._send_selections() 
     523                self.send_selections() 
    270524 
    271525    def selection_updated_callback(self): 
    272526        if self.plot.selection_type != SelectionType.ZOOM and self.auto_send_selection_update: 
    273             self._send_selections() 
    274  
    275     def _send_selections(self): 
    276         # TODO: implement precise get_selection_indices 
    277         indices = self.plot.get_selection_indices() 
    278         if len(indices) < 1: 
    279             return 
    280  
    281         selected_indices = [1 if i in indices else 0 
    282                             for i in range(len(self.data))] 
    283         unselected_indices = [1-i for i in selected_indices] 
    284         selected = self.plot.rawData.selectref(selected_indices) 
    285         unselected = self.plot.rawData.selectref(unselected_indices) 
    286  
    287         if len(selected) == 0: 
    288             selected = None 
    289         if len(unselected) == 0: 
    290             unselected = None 
    291  
    292         self.send('Selected Examples', selected) 
    293         self.send('Unselected Examples', unselected) 
     527            self.send_selections() 
    294528 
    295529    def change_selection_type(self): 
     
    299533 
    300534    def set_data(self, data=None): 
    301         self.closeContext("") 
     535        self.closeContext() 
     536        self.vizrank.clearResults() 
     537        same_domain = self.data and data and\ 
     538            data.domain.checksum() == self.data.domain.checksum() 
    302539        self.data = data 
    303         self.plot.set_data(data, self.subsetData) 
     540        if not same_domain: 
     541            self.init_attr_values() 
     542        self.openContext('', data) 
     543 
     544    def init_attr_values(self): 
    304545        self.x_attr_cb.clear() 
    305546        self.y_attr_cb.clear() 
     
    307548        self.color_attr_cb.clear() 
    308549        self.size_attr_cb.clear() 
    309         self.shape_attr_cb.clear() 
     550        self.symbol_attr_cb.clear() 
    310551        self.label_attr_cb.clear() 
    311552 
    312553        self.discrete_attrs = {} 
    313554 
    314         if self.data is not None: 
    315             self.all_attrs = data.domain.variables + data.domain.getmetas().values() 
    316             self.candidate_attrs = [attr for attr in self.all_attrs if attr.varType in [Discrete, Continuous]] 
    317  
    318             self.attr_name_index = {} 
    319             for i, attr in enumerate(self.all_attrs): 
    320                 self.attr_name_index[attr.name] = i 
    321  
    322             self.attr_name = {} 
    323             for i, attr in enumerate(self.all_attrs): 
    324                 self.attr_name[i] = attr.name 
    325  
    326             self.color_attr_cb.addItem('(Same color)') 
    327             self.size_attr_cb.addItem('(Same size)') 
    328             self.shape_attr_cb.addItem('(Same shape)') 
    329             self.label_attr_cb.addItem('(No labels)') 
    330             icons = OWGUI.getAttributeIcons()  
    331             for (i, attr) in enumerate(self.candidate_attrs): 
     555        if not self.data: 
     556            return 
     557 
     558        self.color_attr_cb.addItem('(Same color)') 
     559        self.label_attr_cb.addItem('(No labels)') 
     560        self.symbol_attr_cb.addItem('(Same symbol)') 
     561        self.size_attr_cb.addItem('(Same size)') 
     562 
     563        icons = OWGUI.getAttributeIcons()  
     564        for metavar in [self.data.domain.getmeta(mykey) for mykey in self.data.domain.getmetas().keys()]: 
     565            self.label_attr_cb.addItem(icons[metavar.varType], metavar.name) 
     566 
     567        for attr in self.data.domain: 
     568            if attr.varType in [Discrete, Continuous]: 
    332569                self.x_attr_cb.addItem(icons[attr.varType], attr.name) 
    333570                self.y_attr_cb.addItem(icons[attr.varType], attr.name) 
     
    335572                self.color_attr_cb.addItem(icons[attr.varType], attr.name) 
    336573                self.size_attr_cb.addItem(icons[attr.varType], attr.name) 
    337                 self.label_attr_cb.addItem(icons[attr.varType], attr.name) 
    338                 if attr.varType == orange.VarTypes.Discrete: 
    339                     self.discrete_attrs[len(self.discrete_attrs)+1] = (i, attr) 
    340                     self.shape_attr_cb.addItem(icons[orange.VarTypes.Discrete], attr.name) 
    341  
    342             array, c, w = self.data.toNumpyMA() 
    343             if len(c): 
    344                 array = numpy.hstack((array, c.reshape(-1,1))) 
    345             self.data_array = array 
    346  
    347             self.x_attr, self.y_attr, self.z_attr = numpy.min([[0, 1, 2], 
    348                                                                [len(self.candidate_attrs) - 1]*3 
    349                                                               ], axis=0) 
    350             self.color_attr = 0 
    351             self.shown_attr_indices = [self.x_attr, self.y_attr, self.z_attr, self.color_attr] 
    352             self.openContext('', data) 
     574            if attr.varType == Discrete:  
     575                self.symbol_attr_cb.addItem(icons[attr.varType], attr.name) 
     576            self.label_attr_cb.addItem(icons[attr.varType], attr.name) 
     577 
     578        self.x_attr = str(self.x_attr_cb.itemText(0)) 
     579        if self.y_attr_cb.count() > 1: 
     580            self.y_attr = str(self.y_attr_cb.itemText(1)) 
     581        else: 
     582            self.y_attr = str(self.y_attr_cb.itemText(0)) 
     583 
     584        if self.z_attr_cb.count() > 2: 
     585            self.z_attr = str(self.z_attr_cb.itemText(2)) 
     586        else: 
     587            self.z_attr = str(self.z_attr_cb.itemText(0)) 
     588 
     589        if self.data.domain.classVar and self.data.domain.classVar.varType in [Discrete, Continuous]: 
     590            self.color_attr = self.data.domain.classVar.name 
     591        else: 
     592            self.color_attr = '' 
     593 
     594        self.symbol_attr = self.size_attr = self.label_attr = '' 
     595        self.shown_attr_indices = [self.x_attr, self.y_attr, self.z_attr, self.color_attr] 
    353596 
    354597    def set_subset_data(self, data=None): 
    355         self.subsetData = data 
     598        self.subset_data = data 
    356599 
    357600    def handleNewSignals(self): 
     601        self.vizrank.resetDialog() 
     602        self.plot.set_data(self.data, self.subset_data) 
    358603        self.update_plot() 
    359604        self.send_selections() 
     
    363608 
    364609    def sendReport(self): 
    365         self.startReport('%s [%s - %s - %s]' % (self.windowTitle(), self.attr_name[self.x_attr], 
    366                                                 self.attr_name[self.y_attr], self.attr_name[self.z_attr])) 
     610        self.startReport('%s [%s - %s - %s]' % (self.windowTitle(), self.x_attr, self.y_attr, self.z_attr)) 
    367611        self.reportSettings('Visualized attributes', 
    368                             [('X', self.attr_name[self.x_attr]), 
    369                              ('Y', self.attr_name[self.y_attr]), 
    370                              ('Z', self.attr_name[self.z_attr]), 
    371                              self.color_attr and ('Color', self.attr_name[self.color_attr]), 
    372                              self.label_attr and ('Label', self.attr_name[self.label_attr]), 
    373                              self.shape_attr and ('Shape', self.attr_name[self.shape_attr]), 
    374                              self.size_attr  and ('Size', self.attr_name[self.size_attr])]) 
     612                            [('X', self.x_attr), 
     613                             ('Y', self.y_attr), 
     614                             ('Z', self.z_attr), 
     615                             self.color_attr and ('Color', self.color_attr), 
     616                             self.label_attr and ('Label', self.label_attr), 
     617                             self.symbol_attr and ('Symbol', self.symbol_attr), 
     618                             self.size_attr  and ('Size', self.size_attr)]) 
    375619        self.reportSettings('Settings', 
    376620                            [('Symbol size', self.plot.symbol_scale), 
    377621                             ('Transparency', self.plot.transparency), 
    378                              ("Jittering", self.jitter_size), 
    379                              ("Jitter continuous attributes", OWGUI.YesNo[self.jitter_continuous]) 
     622                             ('Jittering', self.jitter_size), 
     623                             ('Jitter continuous attributes', OWGUI.YesNo[self.jitter_continuous]) 
    380624                             ]) 
    381625        self.reportSection('Plot') 
     
    410654            return 
    411655 
    412         self.x_attr_discrete = self.y_attr_discrete = self.z_attr_discrete = False 
    413  
    414         if self.candidate_attrs[self.x_attr].varType == Discrete: 
    415             self.x_attr_discrete = True 
    416         if self.candidate_attrs[self.y_attr].varType == Discrete: 
    417             self.y_attr_discrete = True 
    418         if self.candidate_attrs[self.z_attr].varType == Discrete: 
    419             self.z_attr_discrete = True 
    420  
    421         X, Y, Z, mask = self.get_axis_data(self.x_attr, self.y_attr, self.z_attr) 
    422  
    423         color_discrete = shape_discrete = size_discrete = False 
    424  
    425         if self.color_attr > 0: 
    426             color_attr = self.candidate_attrs[self.color_attr - 1] 
    427             C = self.data_array[:, self.color_attr - 1] 
    428             if color_attr.varType == Discrete: 
    429                 color_discrete = True 
    430                 palette = OWColorPalette.ColorPaletteHSV(len(color_attr.values)) 
    431                 colors = [palette[int(value)] for value in C.ravel()] 
    432                 colors = [[c.red()/255., c.green()/255., c.blue()/255., self.alpha_value/255.] for c in colors] 
    433                 palette_colors = [palette[i] for i in range(len(color_attr.values))] 
    434             else: 
    435                 palette = OWColorPalette.ColorPaletteBW() 
    436                 maxC, minC = numpy.max(C), numpy.min(C) 
    437                 C = (C - minC) / (maxC - minC) 
    438                 colors = [palette[value] for value in C.ravel()] 
    439                 colors = [[c.red()/255., c.green()/255., c.blue()/255., self.alpha_value/255.] for c in colors] 
    440         else: 
    441             colors = 'b' 
    442  
    443         if self.size_attr > 0: 
    444             size_attr = self.candidate_attrs[self.size_attr - 1] 
    445             S = self.data_array[:, self.size_attr - 1] 
    446             if size_attr.varType == Discrete: 
    447                 size_discrete = True 
    448                 sizes = [v+1. for v in S] 
    449             else: 
    450                 min, max = numpy.min(S), numpy.max(S) 
    451                 sizes = [(v - min) / (max-min) for v in S] 
    452         else: 
    453             sizes = 1. 
    454  
    455         shapes = None 
    456         if self.shape_attr > 0: 
    457             i, shape_attr = self.discrete_attrs[self.shape_attr] 
    458             if shape_attr.varType == Discrete: 
    459                 shape_discrete = True 
    460                 shapes = self.data_array[:, i] 
    461  
    462         labels = None 
    463         if self.label_attr > 0: 
    464             label_attr = self.candidate_attrs[self.label_attr - 1] 
    465             labels = self.data_array[:, self.label_attr - 1] 
    466             if label_attr.varType == Discrete: 
    467                 value_map = {key: label_attr.values[key] for key in range(len(label_attr.values))} 
    468                 labels = [value_map[value] for value in labels] 
    469  
    470         self.plot.clear() 
    471  
    472         if self.plot.show_legend: 
    473             legend_keys = {} 
    474             color_attr = color_attr if self.color_attr > 0 and color_discrete else None 
    475             size_attr = size_attr if self.size_attr > 0 and size_discrete else None 
    476             shape_attr = shape_attr if self.shape_attr > 0 and shape_discrete else None 
    477  
    478             single_legend = [color_attr, size_attr, shape_attr].count(None) == 2 
    479             if single_legend: 
    480                 legend_join = lambda name, val: val 
    481             else: 
    482                 legend_join = lambda name, val: name + '=' + val  
    483  
    484             if color_attr != None: 
    485                 num = len(color_attr.values) 
    486                 val = [[], [], [1.]*num, [Symbol.RECT]*num] 
    487                 var_values = getVariableValuesSorted(self.data.domain[self.attr_name_index[color_attr.name]]) 
    488                 for i in range(num): 
    489                     val[0].append(legend_join(color_attr.name, var_values[i])) 
    490                     c = palette_colors[i] 
    491                     val[1].append([c.red()/255., c.green()/255., c.blue()/255., 1.]) 
    492                 legend_keys[color_attr] = val 
    493  
    494             if shape_attr != None: 
    495                 num = len(shape_attr.values) 
    496                 if legend_keys.has_key(shape_attr): 
    497                     val = legend_keys[shape_attr] 
    498                 else: 
    499                     val = [[], [(0, 0, 0, 1)]*num, [1.]*num, []] 
    500                 var_values = getVariableValuesSorted(self.data.domain[self.attr_name_index[shape_attr.name]]) 
    501                 val[3] = [] 
    502                 val[0] = [] 
    503                 for i in range(num): 
    504                     val[3].append(i) 
    505                     val[0].append(legend_join(shape_attr.name, var_values[i])) 
    506                 legend_keys[shape_attr] = val 
    507  
    508             if size_attr != None: 
    509                 num = len(size_attr.values) 
    510                 if legend_keys.has_key(size_attr): 
    511                     val = legend_keys[size_attr] 
    512                 else: 
    513                     val = [[], [(0, 0, 0, 1)]*num, [], [Symbol.RECT]*num] 
    514                 val[2] = [] 
    515                 val[0] = [] 
    516                 var_values = getVariableValuesSorted(self.data.domain[self.attr_name_index[size_attr.name]]) 
    517                 for i in range(num): 
    518                     val[0].append(legend_join(size_attr.name, var_values[i])) 
    519                     val[2].append(0.1 + float(i) / len(var_values)) 
    520                 legend_keys[size_attr] = val 
    521         else: 
    522             legend_keys = {} 
    523  
    524         for val in legend_keys.values(): 
    525             for i in range(len(val[1])): 
    526                 self.plot.legend.add_item(val[3][i], val[1][i], val[2][i], val[0][i]) 
    527  
    528         self.plot.scatter(X, Y, Z, colors, sizes, shapes, labels) 
    529         self.plot.set_x_axis_title(self.candidate_attrs[self.x_attr].name) 
    530         self.plot.set_y_axis_title(self.candidate_attrs[self.y_attr].name) 
    531         self.plot.set_z_axis_title(self.candidate_attrs[self.z_attr].name) 
    532  
    533         def create_discrete_map(attr_index): 
    534             values = self.candidate_attrs[attr_index].values 
    535             return {key: value for key, value in enumerate(values)} 
    536  
    537         if self.candidate_attrs[self.x_attr].varType == Discrete: 
    538             self.plot.set_x_axis_map(create_discrete_map(self.x_attr)) 
    539         if self.candidate_attrs[self.y_attr].varType == Discrete: 
    540             self.plot.set_y_axis_map(create_discrete_map(self.y_attr)) 
    541         if self.candidate_attrs[self.z_attr].varType == Discrete: 
    542             self.plot.set_z_axis_map(create_discrete_map(self.z_attr)) 
    543  
    544     def get_axis_data(self, x_index, y_index, z_index): 
    545         array = self.data_array 
    546         X, Y, Z = array[:, x_index], array[:, y_index], array[:, z_index] 
    547  
    548         if self.jitter_size > 0: 
    549             X, Y, Z = map(numpy.copy, [X, Y, Z]) 
    550             x_range = numpy.max(X)-numpy.min(X) 
    551             y_range = numpy.max(Y)-numpy.min(Y) 
    552             z_range = numpy.max(Z)-numpy.min(Z) 
    553             if self.x_attr_discrete or self.jitter_continuous: 
    554                 X += (numpy.random.random(len(X))-0.5) * (self.jitter_size * x_range / 100.) 
    555             if self.y_attr_discrete or self.jitter_continuous: 
    556                 Y += (numpy.random.random(len(Y))-0.5) * (self.jitter_size * y_range / 100.) 
    557             if self.z_attr_discrete or self.jitter_continuous: 
    558                 Z += (numpy.random.random(len(Z))-0.5) * (self.jitter_size * z_range / 100.) 
    559             self.data_array_jittered = (X, Y, Z) 
    560         return X, Y, Z, None 
     656        self.plot.update_data(self.x_attr, self.y_attr, self.z_attr, 
     657                              self.color_attr, self.symbol_attr, self.size_attr, 
     658                              self.label_attr) 
    561659 
    562660    def showSelectedAttributes(self): 
     
    564662        if not val: return 
    565663        if self.data.domain.classVar: 
    566             self.attr_color = self.attr_name_index[self.data.domain.classVar.name] 
     664            self.attr_color = self.data.domain.classVar.name 
    567665        if not self.plot.have_data: 
    568666            return 
    569667        attr_list = val[3] 
    570668        if attr_list and len(attr_list) == 3: 
    571             self.x_attr = self.attr_name_index[attr_list[0]] 
    572             self.y_attr = self.attr_name_index[attr_list[1]] 
    573             self.z_attr = self.attr_name_index[attr_list[2]] 
    574  
    575         #if self.graph.dataHasDiscreteClass and (self.vizrank.showKNNCorrectButton.isChecked() or self.vizrank.showKNNWrongButton.isChecked()): 
    576         #    kNNExampleAccuracy, probabilities = self.vizrank.kNNClassifyData(self.graph.createProjectionAsExampleTable([self.graph.attributeNameIndex[self.attrX], self.graph.attributeNameIndex[self.attrY]])) 
    577         #    if self.vizrank.showKNNCorrectButton.isChecked(): kNNExampleAccuracy = ([1.0 - val for val in kNNExampleAccuracy], "Probability of wrong classification = %.2f%%") 
    578         #    else: kNNExampleAccuracy = (kNNExampleAccuracy, "Probability of correct classification = %.2f%%") 
    579         #else: 
    580         #    kNNExampleAccuracy = None 
    581         #self.graph.insideColors = insideColors or self.classificationResults or kNNExampleAccuracy or self.outlierValues 
    582         #self.graph.updateData(self.attrX, self.attrY, self.attrColor, self.attrShape, self.attrSize, self.attrLabel) 
     669            self.x_attr = attr_list[0] 
     670            self.y_attr = attr_list[1] 
     671            self.z_attr = attr_list[2] 
     672 
    583673        self.update_plot() 
    584674 
    585 if __name__ == "__main__": 
     675if __name__ == '__main__': 
    586676    app = QApplication(sys.argv) 
    587677    w = OWScatterPlot3D() 
    588     data = orange.ExampleTable("../../doc/datasets/iris") 
     678    data = orange.ExampleTable('../../doc/datasets/iris') 
    589679    w.set_data(data) 
    590680    w.handleNewSignals() 
Note: See TracChangeset for help on using the changeset viewer.