Changeset 8241:d8e47aa467bd in orange


Ignore:
Timestamp:
08/20/11 16:19:07 (3 years ago)
Author:
Noughmad <Noughmad@…>
Branch:
default
Convert:
5103d7e5bd4e33dbf41fdaee6563ec2718614145
Message:

Finish the basic plot example, and add some fixes to support it.

Location:
orange
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/OWColorPalette.py

    r8042 r8241  
    539539        if type(index) == tuple: 
    540540            index, brightness = index 
    541         index = int(index) 
    542541         
    543542        if self.numberOfColors == -1:     # is this color for continuous attribute? 
     
    546545            return col 
    547546        else: 
     547            index = int(index) 
    548548            if index < len(self.rgbColors): 
    549549                if brightness == None: 
  • orange/OrangeWidgets/plot/owaxis.py

    r8231 r8241  
    9393        self._ticks = [] 
    9494        major, medium, minor = self.tick_length 
    95         if self.labels is not None: 
     95        if self.labels is not None and not self.auto_scale: 
    9696            for i, text in enumerate(self.labels): 
    9797                self._ticks.append( ( i, text, medium, 1 ) ) 
    9898        else: 
    99             if self.scale: 
     99            if self.scale and not self.auto_scale: 
    100100                min, max, step = self.scale 
    101101            elif self.auto_range: 
  • orange/OrangeWidgets/plot/owplot.py

    r8240 r8241  
    271271            :rtype: list of int 
    272272             
    273          
    274      
     273    **Color schemes** 
     274     
     275        By default, OWPlot uses the application's system palette for drawing everything 
     276        except data curves and points. This way, it maintains consistency with other application 
     277        with regards to the user interface.  
     278         
     279        If data is plotted with no color specified, it will use a system color as well,  
     280        so that a good contrast with the background in guaranteed.  
     281         
     282        OWPlot uses the :meth:`.OWidget.palette` to determine its color scheme, so it can be  
     283        changed using :meth:`.QWidget.setPalette`. There are also two predefined color schemes: 
     284        ``OWPalette.Dark`` and ``OWPalette.Light``, which provides a dark and a light scheme 
     285        respectively.  
     286         
     287        .. attribute:: theme_name 
     288         
     289            A string attribute with three possible values: 
     290            ==============  =========================== 
     291            Value           Meaning 
     292            --------------  --------------------------- 
     293            "default"       The system palette is used 
     294            "dark"          The dark theme is used 
     295            "light"         The light theme is used  
     296            ==============  =========================== 
     297             
     298            To apply the settings, first set this attribute's value, and then call :meth:`update_theme` 
     299             
     300        .. automethod:: update_theme 
     301             
     302        On the other hand, curves with a specified color will use colors from Orange's palette,  
     303        which can be configured within Orange. Each plot contains two separate palettes:  
     304        one for continuous attributes, and one for discrete ones. Both are created by 
     305        :obj:`.OWColorPalette.ColorPaletteGenerator` 
     306         
     307        .. attribute:: continuous_palette 
     308         
     309            The palette used when point color represents a continuous attribute 
     310         
     311        .. attribute:: discrete_palette 
     312         
     313            The palette used when point color represents a discrete attribute 
     314 
    275315    """ 
    276316     
     
    322362        self.show_filled_symbols = True 
    323363        self.alpha_value = 255 
    324         self.show_grid = False 
     364        self.show_grid = True 
    325365         
    326366        self.curveSymbols = range(13) 
     
    389429                self.add_axis(key) 
    390430                 
    391         self.contPalette = ColorPaletteGenerator(numberOfColors = -1) 
    392         self.discPalette = ColorPaletteGenerator() 
     431        self.continuous_palette = ColorPaletteGenerator(numberOfColors = -1) 
     432        self.discrete_palette = ColorPaletteGenerator() 
    393433         
    394434        self.gui = OWPlotGUI(self) 
     
    413453    showMainTitle = deprecated_attribute("showMainTitle", "show_main_title") 
    414454    gridCurve = deprecated_attribute("gridCurve", "grid_curve") 
     455    contPalette = deprecated_attribute("contPalette", "continuous_palette") 
     456    discPalette = deprecated_attribute("discPalette", "discrete_palette") 
    415457     
    416458    def __setattr__(self, name, value): 
     
    10201062        self.update_zoom() 
    10211063        self.update_axes() 
     1064        self.update_grid() 
    10221065        self.update_filled_symbols() 
    10231066        self.setSceneRect(QRectF(self.contentsRect())) 
     
    17061749             
    17071750    def set_palette(self, p): 
     1751        ''' 
     1752            Sets the plot palette to ``p``.  
     1753             
     1754            :param p: The new color palette 
     1755            :type p: :obj:`.QPalette` 
     1756        ''' 
    17081757        self.setPalette(p) 
    17091758        self.replot() 
    17101759         
    17111760    def update_theme(self): 
     1761        ''' 
     1762            Updates the current color theme, depending on the value of :attr:`theme_name`. 
     1763        ''' 
    17121764        if self.theme_name.lower() == 'default': 
    17131765            self.set_palette(OWPalette.System) 
  • orange/doc/widgets/default.htm

    r8190 r8241  
    1717<li><A href="progressbar.htm">Progress Bar</a></li> 
    1818<li><A href="graphing.htm">Graphing</a></li> 
    19 <li><A href="plots.htm">Plots with OWPlot</a></li> 
     19<li><A href="plots-basic.htm">Plots with OWPlot</a></li> 
     20<li><A href="plots.htm">Switching to OWPlot</a></li> 
    2021<li><A href="context-settings.htm">Advanced topic: Context Dependent Settings</a></li> 
    2122</ul> 
  • orange/doc/widgets/owplot_example.py

    r8239 r8241  
    1212class BasicWidget(OWWidget): 
    1313    def __init__(self, parent=None, signalManager=None): 
    14         OWWidget.__init__(self, parent, signalManager, 'Basic') 
     14        OWWidget.__init__(self, parent, signalManager, 'Simple plot') 
    1515        self.inputs = [("Examples", ExampleTable, self.set_data)] 
    1616         
    1717        self.plot = BasicPlot(self.mainArea, "Example plot", widget = self) 
    1818        self.mainArea.layout().addWidget(self.plot) 
    19         random.seed(7) 
     19        random.seed() 
    2020        self.time_id = self.startTimer(5000) 
    2121             
     
    2626        self.data = data 
    2727        domain = data.domain 
    28         n = len(data.domain) # The number of attributes in data 
    2928         
    30         y_i, x_i, c_i, s_i = [int(random.random() * n) for i in range(4)] 
    31         qDebug(' '.join(str(i) for i in [y_i, x_i, c_i, s_i])) 
     29        y_i, x_i, c_i, s_i = [int(random.random() * len(domain)) for i in range(4)] 
    3230         
    3331        self.plot.set_axis_title(xBottom, domain[x_i].name) 
     
    4038        else: 
    4139            self.plot.set_axis_autoscale(xBottom) 
     40 
    4241        if data.domain[y_i].varType == orange.VarTypes.Discrete: 
    4342            self.plot.set_axis_labels(yLeft, get_variable_values_sorted(domain[y_i])) 
     
    5049        s_data = [] 
    5150         
    52         color_cont = False 
     51        color_cont = (domain[c_i].varType == orange.VarTypes.Continuous) 
    5352         
    54         if domain[c_i].varType == orange.VarTypes.Discrete: 
    55             palette = self.plot.discPalette 
    56         else: 
    57             palette = self.plot.contPalette 
    58             color_cont = True 
    59          
    60         legend_colors = set() 
    6153        legend_sizes = set() 
    6254         
    6355        for e in data: 
    6456            x_data.append(e[x_i]) 
    65             y_data.append(e[y_i]) 
    66             color = QColor(*palette.getRGB(e[c_i])) 
    67             c_data.append(color) 
     57            y_data.append(e[y_i])  
     58            c_data.append(e[c_i]) 
    6859            size = 5 + round(e[s_i]) 
    6960            s_data.append(size) 
    7061             
    71             if color_cont: 
    72                 legend_colors.add(float(e[c_i])) 
    73             else:    
    74                 legend_colors.add( (color, int(e[c_i])) )  
    7562            legend_sizes.add( (size, float(e[s_i])) ) 
    7663             
     64        if color_cont: 
     65            m = min(c_data) 
     66            M = max(c_data) 
     67            legend_colors = set(float(c) for c in c_data) 
     68            c_data = [self.plot.continuous_palette[(v-m)/(M-m)] for v in c_data] 
     69        else: 
     70            _colors = [self.plot.discrete_palette.getRGB(i) for i in c_data] 
     71            _values = set([float(c) for c in c_data]) 
     72            legend_colors = zip([QColor(*c) for c in set(_colors)], _values) 
     73            c_data = [QColor(*c) for c in _colors] 
     74                         
    7775        self.plot.legend().clear() 
    7876             
    7977        if domain[s_i].varType == orange.VarTypes.Discrete: 
    8078            for size, value in legend_sizes: 
    81                 self.plot.legend().add_item( domain[s_i].name, "%.1f" % value, OWPoint(OWPoint.Diamond, self.plot.color(OWPalette.Data), size) ) 
     79                self.plot.legend().add_item( domain[s_i].name, domain[s_i].values[int(value)], OWPoint(OWPoint.Diamond, self.plot.color(OWPalette.Data), size) ) 
    8280             
    8381        if color_cont: 
     
    8583        else: 
    8684            for color, value in legend_colors: 
    87                 self.plot.legend().add_item( domain[c_i].name, "%.1f" % value, OWPoint(OWPoint.Diamond, color, 5) ) 
     85                self.plot.legend().add_item( domain[c_i].name, domain[c_i].values[int(value)], OWPoint(OWPoint.Diamond, color, 5) ) 
    8886                    
    8987        self.plot.set_main_curve_data(x_data, y_data, color_data=c_data, label_data = [], size_data=s_data, shape_data = [OWPoint.Diamond]) 
     88        self.plot.replot() 
    9089         
    9190    def timerEvent(self, event): 
    9291        self.set_data(self.data) 
     92         
     93    def sizeHint(self): 
     94        return QSize(600, 400) 
    9395     
    9496     
  • orange/doc/widgets/plots-basic.htm

    r8239 r8241  
    2222</p> 
    2323 
     24<img src="owplot_example.png" /> 
     25 
    2426<p>The central method for plotting a series of points is 
    2527<code>set_main_curve_data()</code>. It creates a curve and adds it to the plot, or 
    2628just updates it if one already exists. Because it doesn't recreate the curve every time 
    2729it's called, it can animate the transition from one data set to another. </p> 
     30 
     31<h2>Setting the data</h2> 
    2832 
    2933<p>To use this method, we must first convert the data to lists, one list for every property:  
     
    3337<code>preprocess.scaling</code> module.</p> 
    3438 
    35 <xmp class="code"> 
     39<xmp class="code">color_cont = (domain[c_i].varType == orange.VarTypes.Continuous) 
     40   
    3641for e in data: 
    3742    x_data.append(e[x_i]) 
    38     y_data.append(e[y_i]) 
    39     color = QColor(*palette.getRGB(e[c_i])) 
    40     c_data.append(color) 
     43    y_data.append(e[y_i])  
     44    c_data.append(e[c_i]) 
    4145    size = 5 + round(e[s_i]) 
    4246    s_data.append(size) 
     47     
     48if color_cont: 
     49    m = min(c_data) 
     50    M = max(c_data) 
     51    c_data = [self.plot.continuous_palette[(v-m)/(M-m)] for v in c_data] 
     52else: 
     53    c_data = [QColor(*self.plot.discrete_palette.getRGB(i)) for i in c_data]         
    4354</xmp> 
     55 
     56<p>You can see that we have to adjust the color attribute in case that attribute is continuous.  
     57This is becouse OWPaletteGenerator only accepts values between 0 and 1 for such attributes.  
     58So we have to shrink the whole intervale to [0,1] before assigning any colors.</p> 
    4459 
    4560<p>Once we have the data lists, it's time to plot them:</p> 
     
    4762<xmp class="code"> 
    4863self.plot.set_main_curve_data(x_data, y_data, color_data=c_data, size_data=s_data) 
     64self.plot.replot() 
    4965</xmp> 
     66 
     67<h2>Showing a legend</h2> 
     68The points sure look nice, but how do we know what color represents what value? 
     69We show a legend. Unfortunately, using <code>set_main_curve_data()</code> can't 
     70guess the names and values of all attributes, so we must do it ourselves.  
     71Still, it isn't much work.</p> 
     72 
     73<p>First, we extend the loop for earlier to store colors and sizes in a set:</p> 
     74 
     75<xmp class="code">color_cont = (domain[c_i].varType == orange.VarTypes.Continuous) 
     76   
     77legend_sizes = set() 
     78 
     79for e in data: 
     80    x_data.append(e[x_i]) 
     81    y_data.append(e[y_i])  
     82    c_data.append(e[c_i]) 
     83    size = 5 + round(e[s_i]) 
     84    s_data.append(size) 
     85     
     86    legend_sizes.add( (size, float(e[s_i])) ) 
     87     
     88if color_cont: 
     89    m = min(c_data) 
     90    M = max(c_data) 
     91    legend_colors = set(float(c) for c in c_data) 
     92    c_data = [self.plot.continuous_palette[(v-m)/(M-m)] for v in c_data] 
     93else: 
     94    _colors = [self.plot.discrete_palette.getRGB(i) for i in c_data] 
     95    _values = set([float(c) for c in c_data]) 
     96    legend_colors = zip([QColor(*c) for c in set(_colors)], _values) 
     97    c_data = [QColor(*c) for c in _colors]         
     98</xmp> 
     99 
     100<p>The logic for storing all possible sizes is quite simple:  
     101we create a set that holds them. Unfortunately, handling colors is bit more complex,  
     102because we first store (R,G,B) tuples in a set, and then convert them to QColor.  
     103Also, the approach differs for continuous or discrete color attributes.</p> 
     104 
     105<p>Now we have a set all colors and sizes we need to display in the legend.  
     106<code>legend_colors</code> and <code>legend_sizes</code> are both sets because 
     107we only want one legend item for each possible value, no matter how many 
     108points share that value. Now all that's left is adding the legend items:</p> 
     109 
     110<xmp class="code">self.plot.legend().clear() 
     111 
     112if domain[s_i].varType == orange.VarTypes.Discrete: 
     113    for size, value in legend_sizes: 
     114        self.plot.legend().add_item( domain[s_i].name, domain[s_i].values[int(value)], OWPoint(OWPoint.Diamond, self.plot.color(OWPalette.Data), size) ) 
     115     
     116if color_cont: 
     117    self.plot.legend().add_color_gradient(domain[c_i].name, ("%.1f" % min(legend_colors), "%.1f" % max(legend_colors))) 
     118else: 
     119    for color, value in legend_colors: 
     120        self.plot.legend().add_item( domain[c_i].name, domain[c_i].values[int(value)], OWPoint(OWPoint.Diamond, color, 5) ) 
     121</xmp> 
     122 
     123<p>We only show a legend for the size attribute if it's discrete.  
     124However, we show the color attribute in both cases.  
     125If it's continuous, only one item is created with a color gradient.</p> 
     126 
     127<h2>Running this example</h2> 
     128<p>You can find the full code for the example <a href="owplot_example.py">here</a>. </p> 
     129<p>This particular example has a timer, so that <code>set_data</code> is called every 
     130five seconds, and attributes are chosen at random each time, athough always  
     131from the same data set. </p> 
     132 
     133 
  • orange/doc/widgets/plots.htm

    r8238 r8241  
    1919most methods also found in the Qwt-based OWGraph, so switching from one base 
    2020to another is quite easy. </p> 
     21 
     22<p>Creating a new plot using OWPlot is described in <a href="plots-basic.htm">Plots with OWPlot</a>.  
     23This topic tries to show the similarities between the plot module and the old Qwt-based graph. </p> 
    2124 
    2225<h2>Plots</h2> 
Note: See TracChangeset for help on using the changeset viewer.