Changeset 9483:a0f1e6b2fcdf in orange


Ignore:
Timestamp:
08/16/11 14:21:56 (3 years ago)
Author:
matija <matija.polajnar@…>
Branch:
default
Convert:
f2dfbdaf4bdad51f659a8d80993bd84f10bb456a
Message:

Merge trunk into MLC branch.

Location:
orange
Files:
74 added
3 deleted
96 edited

Legend:

Unmodified
Added
Removed
  • orange/Orange/__init__.py

    r9474 r9483  
    9797_import("misc.render") 
    9898_import("misc.selection") 
    99 _import("misc.r") 
     99#_import("misc.r") 
  • orange/Orange/classification/bayes.py

    r9450 r9483  
    1 """  
    2 .. index:: naive Bayes classifier 
    3     
    4 .. index::  
    5    single: classification; naive Bayes classifier 
    6  
    7 ********************************** 
    8 Naive Bayes classifier (``bayes``) 
    9 ********************************** 
    10  
    11 The most primitive Bayesian classifier is :obj:`NaiveLearner`.  
    12 `Naive Bayes classification algorithm <http://en.wikipedia.org/wiki/Naive_Bayes_classifier>`_  
    13 estimates conditional probabilities from training data and uses them 
    14 for classification of new data instances. The algorithm learns very fast if all features 
    15 in the training data set are discrete. If a number of features are continues, though, the  
    16 algorithm runs slower due to time spent to estimate continuous conditional distributions. 
    17  
    18 The following example demonstrates a straightforward invocation of 
    19 this algorithm (`bayes-run.py`_, uses `titanic.tab`_): 
    20  
    21 .. literalinclude:: code/bayes-run.py 
    22    :lines: 7- 
    23  
    24 .. index:: Naive Bayesian Learner 
    25 .. autoclass:: Orange.classification.bayes.NaiveLearner 
    26    :members: 
    27    :show-inheritance: 
    28   
    29 .. autoclass:: Orange.classification.bayes.NaiveClassifier 
    30    :members: 
    31    :show-inheritance: 
    32     
    33     
    34 Examples 
    35 ======== 
    36  
    37 :obj:`NaiveLearner` can estimate probabilities using relative frequencies or 
    38 m-estimate (`bayes-mestimate.py`_, uses `lenses.tab`_): 
    39  
    40 .. literalinclude:: code/bayes-mestimate.py 
    41     :lines: 7- 
    42  
    43 Observing conditional probabilities in an m-estimate based classifier shows a 
    44 shift towards the second class - as compared to probabilities above, where 
    45 relative frequencies were used. Note that the change in error estimation did 
    46 not have any effect on apriori probabilities 
    47 (`bayes-thresholdAdjustment.py`_, uses `adult-sample.tab`_): 
    48  
    49 .. literalinclude:: code/bayes-thresholdAdjustment.py 
    50     :lines: 7- 
    51      
    52 Setting adjustThreshold parameter can sometimes improve the results. Those are 
    53 the classification accuracies of 10-fold cross-validation of a normal naive 
    54 bayesian classifier, and one with an adjusted threshold:: 
    55  
    56     [0.7901746265516516, 0.8280138859667578] 
    57  
    58 Probabilities for continuous features are estimated with \ 
    59 :class:`ProbabilityEstimatorConstructor_loess`. 
    60 (`bayes-plot-iris.py`_, uses `iris.tab`_): 
    61  
    62 .. literalinclude:: code/bayes-plot-iris.py 
    63     :lines: 4- 
    64      
    65 .. image:: code/bayes-iris.png 
    66    :scale: 50 % 
    67  
    68 If petal lengths are shorter, the most probable class is "setosa". Irises with 
    69 middle petal lengths belong to "versicolor", while longer petal lengths indicate 
    70 for "virginica". Critical values where the decision would change are at about 
    71 5.4 and 6.3. 
    72  
    73  
    74 .. _bayes-run.py: code/bayes-run.py 
    75 .. _bayes-thresholdAdjustment.py: code/bayes-thresholdAdjustment.py 
    76 .. _bayes-mestimate.py: code/bayes-mestimate.py 
    77 .. _bayes-plot-iris.py: code/bayes-plot-iris.py 
    78 .. _adult-sample.tab: code/adult-sample.tab 
    79 .. _iris.tab: code/iris.tab 
    80 .. _titanic.tab: code/iris.tab 
    81 .. _lenses.tab: code/lenses.tab 
    82  
    83 Implementation details 
    84 ====================== 
    85  
    86 The following two classes are implemented in C++ (*bayes.cpp*). They are not 
    87 intended to be used directly. Here we provide implementation details for those 
    88 interested. 
    89  
    90 Orange.core.BayesLearner 
    91 ------------------------ 
    92 Fields estimatorConstructor, conditionalEstimatorConstructor and 
    93 conditionalEstimatorConstructorContinuous are empty (None) by default. 
    94  
    95 If estimatorConstructor is left undefined, p(C) will be estimated by relative 
    96 frequencies of examples (see ProbabilityEstimatorConstructor_relative). 
    97 When conditionalEstimatorConstructor is left undefined, it will use the same 
    98 constructor as for estimating unconditional probabilities (estimatorConstructor 
    99 is used as an estimator in ConditionalProbabilityEstimatorConstructor_ByRows). 
    100 That is, by default, both will use relative frequencies. But when 
    101 estimatorConstructor is set to, for instance, estimate probabilities by 
    102 m-estimate with m=2.0, the same estimator will be used for estimation of 
    103 conditional probabilities, too. 
    104 P(c|vi) for continuous attributes are, by default, estimated with loess (a 
    105 variant of locally weighted linear regression), using 
    106 ConditionalProbabilityEstimatorConstructor_loess. 
    107 The learner first constructs an estimator for p(C). It tries to get a 
    108 precomputed distribution of probabilities; if the estimator is capable of 
    109 returning it, the distribution is stored in the classifier's field distribution 
    110 and the just constructed estimator is disposed. Otherwise, the estimator is 
    111 stored in the classifier's field estimator, while the distribution is left 
    112 empty. 
    113  
    114 The same is then done for conditional probabilities. Different constructors are 
    115 used for discrete and continuous attributes. If the constructed estimator can 
    116 return all conditional probabilities in form of Contingency, the contingency is 
    117 stored and the estimator disposed. If not, the estimator is stored. If there 
    118 are no contingencies when the learning is finished, the resulting classifier's 
    119 conditionalDistributions is None. Alternatively, if all probabilities are 
    120 stored as contingencies, the conditionalEstimators fields is None. 
    121  
    122 Field normalizePredictions is copied to the resulting classifier. 
    123  
    124 Orange.core.BayesClassifier 
    125 --------------------------- 
    126 Class NaiveClassifier represents a naive bayesian classifier. Probability of 
    127 class C, knowing that values of features :math:`F_1, F_2, ..., F_n` are 
    128 :math:`v_1, v_2, ..., v_n`, is computed as :math:`p(C|v_1, v_2, ..., v_n) = \ 
    129 p(C) \\cdot \\frac{p(C|v_1)}{p(C)} \\cdot \\frac{p(C|v_2)}{p(C)} \\cdot ... \ 
    130 \\cdot \\frac{p(C|v_n)}{p(C)}`. 
    131  
    132 Note that when relative frequencies are used to estimate probabilities, the 
    133 more usual formula (with factors of form :math:`\\frac{p(v_i|C)}{p(v_i)}`) and 
    134 the above formula are exactly equivalent (without any additional assumptions of 
    135 independency, as one could think at a first glance). The difference becomes 
    136 important when using other ways to estimate probabilities, like, for instance, 
    137 m-estimate. In this case, the above formula is much more appropriate.  
    138  
    139 When computing the formula, probabilities p(C) are read from distribution, which 
    140 is of type Distribution, and stores a (normalized) probability of each class. 
    141 When distribution is None, BayesClassifier calls estimator to assess the 
    142 probability. The former method is faster and is actually used by all existing 
    143 methods of probability estimation. The latter is more flexible. 
    144  
    145 Conditional probabilities are computed similarly. Field conditionalDistribution 
    146 is of type DomainContingency which is basically a list of instances of 
    147 Contingency, one for each attribute; the outer variable of the contingency is 
    148 the attribute and the inner is the class. Contingency can be seen as a list of 
    149 normalized probability distributions. For attributes for which there is no 
    150 contingency in conditionalDistribution a corresponding estimator in 
    151 conditionalEstimators is used. The estimator is given the attribute value and 
    152 returns distributions of classes. 
    153  
    154 If neither, nor pre-computed contingency nor conditional estimator exist, the 
    155 attribute is ignored without issuing any warning. The attribute is also ignored 
    156 if its value is undefined; this cannot be overriden by estimators. 
    157  
    158 Any field (distribution, estimator, conditionalDistributions, 
    159 conditionalEstimators) can be None. For instance, BayesLearner normally 
    160 constructs a classifier which has either distribution or estimator defined. 
    161 While it is not an error to have both, only distribution will be used in that 
    162 case. As for the other two fields, they can be both defined and used 
    163 complementarily; the elements which are missing in one are defined in the 
    164 other. However, if there is no need for estimators, BayesLearner will not 
    165 construct an empty list; it will not construct a list at all, but leave the 
    166 field conditionalEstimators empty. 
    167  
    168 If you only need probabilities of individual class call BayesClassifier's 
    169 method p(class, example) to compute the probability of this class only. Note 
    170 that this probability will not be normalized and will thus, in general, not 
    171 equal the probability returned by the call operator. 
    172 """ 
    173  
    1741import Orange 
    1752from Orange.core import BayesClassifier as _BayesClassifier 
     
    18512     
    18613    .. 
    187         :param adjustTreshold: sets the corresponding attribute 
    188         :type adjustTreshold: boolean 
     14        :param adjust_threshold: sets the corresponding attribute 
     15        :type adjust_threshold: boolean 
    18916        :param m: sets the :obj:`estimatorConstructor` to 
    19017            :class:`orange.ProbabilityEstimatorConstructor_m` with specified m 
    19118        :type m: integer 
    192         :param estimatorConstructor: sets the corresponding attribute 
    193         :type estimatorConstructor: orange.ProbabilityEstimatorConstructor 
    194         :param conditionalEstimatorConstructor: sets the corresponding attribute 
    195         :type conditionalEstimatorConstructor: 
     19        :param estimator_constructor: sets the corresponding attribute 
     20        :type estimator_constructor: orange.ProbabilityEstimatorConstructor 
     21        :param conditional_estimator_constructor: sets the corresponding attribute 
     22        :type conditional_estimator_constructor: 
    19623                :class:`orange.ConditionalProbabilityEstimatorConstructor` 
    197         :param conditionalEstimatorConstructorContinuous: sets the corresponding 
     24        :param conditional_estimator_constructor_continuous: sets the corresponding 
    19825                attribute 
    199         :type conditionalEstimatorConstructorContinuous:  
     26        :type conditional_estimator_constructor_continuous:  
    20027                :class:`orange.ConditionalProbabilityEstimatorConstructor` 
    20128                 
     
    20532    Constructor parameters set the corresponding attributes. 
    20633     
    207     .. attribute:: adjustTreshold 
     34    .. attribute:: adjust_threshold 
    20835     
    20936        If set and the class is binary, the classifier's 
     
    21946        This attribute is ignored if you also set estimatorConstructor. 
    22047         
    221     .. attribute:: estimatorConstructor 
     48    .. attribute:: estimator_constructor 
    22249     
    22350        Probability estimator constructor for 
     
    22653        Setting this attribute disables the above described attribute m. 
    22754         
    228     .. attribute:: conditionalEstimatorConstructor 
     55    .. attribute:: conditional_estimator_constructor 
    22956     
    23057        Probability estimator constructor 
     
    23259        the estimator for prior probabilities will be used. 
    23360         
    234     .. attribute:: conditionalEstimatorConstructorContinuous 
     61    .. attribute:: conditional_estimator_constructor_continuous 
    23562     
    23663        Probability estimator constructor for conditional probabilities for 
     
    292119      "conditionalEstimatorConstructorContinuous":"conditional_estimator_constructor_continuous", 
    293120      "weightID": "weight_id" 
    294 }, in_place=False)(NaiveLearner) 
     121}, in_place=True)(NaiveLearner) 
    295122 
    296123 
     
    300127    :class:`Orange.core.BayesClassifier` that does the actual classification. 
    301128     
    302     :param baseClassifier: an :class:`Orange.core.BayesLearner` to wrap. If 
     129    :param base_classifier: an :class:`Orange.core.BayesLearner` to wrap. If 
    303130            not set, a new :class:`Orange.core.BayesLearner` is created. 
    304     :type baseClassifier: :class:`Orange.core.BayesLearner` 
     131    :type base_classifier: :class:`Orange.core.BayesLearner` 
    305132     
    306133    .. attribute:: distribution 
     
    312139        An object that returns a probability of class p(C) for a given class C. 
    313140         
    314     .. attribute:: conditionalDistributions 
     141    .. attribute:: conditional_distributions 
    315142     
    316143        A list of conditional probabilities. 
    317144         
    318     .. attribute:: conditionalEstimators 
     145    .. attribute:: conditional_estimators 
    319146     
    320147        A list of estimators for conditional probabilities. 
    321148         
    322     .. attribute:: adjustThreshold 
     149    .. attribute:: adjust_threshold 
    323150     
    324151        For binary classes, this tells the learner to 
     
    328155    """ 
    329156     
    330     def __init__(self, baseClassifier=None): 
    331         if not baseClassifier: baseClassifier = _BayesClassifier() 
    332         self.nativeBayesClassifier = baseClassifier 
    333         for k, v in self.nativeBayesClassifier.__dict__.items(): 
     157    def __init__(self, base_classifier=None): 
     158        if not base_classifier: base_classifier = _BayesClassifier() 
     159        self.native_bayes_classifier = base_classifier 
     160        for k, v in self.native_bayes_classifier.__dict__.items(): 
    334161            self.__dict__[k] = v 
    335162   
     
    347174              :class:`Orange.statistics.Distribution` or a tuple with both 
    348175        """ 
    349         return self.nativeBayesClassifier(instance, result_type, *args, **kwdargs) 
     176        return self.native_bayes_classifier(instance, result_type, *args, **kwdargs) 
    350177 
    351178    def __setattr__(self, name, value): 
    352         if name == "nativeBayesClassifier": 
     179        if name == "native_bayes_classifier": 
    353180            self.__dict__[name] = value 
    354181            return 
    355         if name in self.nativeBayesClassifier.__dict__: 
    356             self.nativeBayesClassifier.__dict__[name] = value 
     182        if name in self.native_bayes_classifier.__dict__: 
     183            self.native_bayes_classifier.__dict__[name] = value 
    357184        self.__dict__[name] = value 
    358185     
     
    370197         
    371198        """ 
    372         return self.nativeBayesClassifier.p(class_, instance) 
     199        return self.native_bayes_classifier.p(class_, instance) 
    373200     
    374201    def __str__(self): 
    375         """return classifier in human friendly format.""" 
    376         nValues=len(self.classVar.values) 
    377         frmtStr=' %10.3f'*nValues 
    378         classes=" "*20+ ((' %10s'*nValues) % tuple([i[:10] for i in self.classVar.values])) 
     202        """Return classifier in human friendly format.""" 
     203        nvalues=len(self.class_var.values) 
     204        frmtStr=' %10.3f'*nvalues 
     205        classes=" "*20+ ((' %10s'*nvalues) % tuple([i[:10] for i in self.class_var.values])) 
    379206         
    380207        return "\n".join([ 
     
    388215                    ("%20s" % i.variable.values[v][:20]) + (frmtStr % tuple(i[v])) 
    389216                    for v in xrange(len(i.variable.values)))] 
    390                 ) for i in self.conditionalDistributions])]) 
     217                ) for i in self.conditional_distributions 
     218                        if i.variable.var_type == Orange.data.variable.Discrete])]) 
    391219             
    392220 
  • orange/Orange/classification/majority.py

    r9450 r9483  
    1717 
    1818    MajorityLearner will most often be used as is, without setting any 
    19     features. Nevertheless, it has two. 
     19    parameters. Nevertheless, it has two. 
    2020 
    21     .. attribute:: estimatorConstructor 
     21    .. attribute:: estimator_constructor 
    2222     
    2323        An estimator constructor that can be used for estimation of 
     
    2626        this class. 
    2727         
    28     .. attribute:: aprioriDistribution 
     28    .. attribute:: apriori_distribution 
    2929     
    3030        Apriori class distribution that is passed to estimator 
     
    3636    same class probabilities. 
    3737 
    38     .. attribute:: defaultVal 
     38    .. attribute:: default_val 
    3939     
    4040        Value that is returned by the classifier. 
    4141     
    42     .. attribute:: defaultDistribution 
     42    .. attribute:: default_distribution 
    4343 
    4444        Class probabilities returned by the classifier. 
    4545 
    4646The ConstantClassifier's constructor can be called without arguments, 
    47 with value (for defaultVal), variable (for classVar). If the value is 
    48 given and is of type orange.Value (alternatives are an integer index 
    49 of a discrete value or a continuous value), its field variable is will 
    50 either be used for initializing classVar if variable is not given as 
     47with value (for default_val), variable (for class_var). If the value is 
     48given and is of type Orange.data.Value (alternatives are an integer index 
     49of a discrete value or a continuous value), its field variable will 
     50either be used for initializing class_var if variable is not given as 
    5151an argument, or checked against the variable argument, if it is given.  
    5252 
  • orange/Orange/classification/tree.py

    r9450 r9483  
    7171If node is None, we have a null-node; null nodes don't count, so we 
    7272return 0. Otherwise, the size is 1 (this node) plus the sizes of all 
    73 subtrees. The node is an internal node if it has a :obj:`branchSelector`; 
     73subtrees. The node is an internal node if it has a :obj:`branch_selector`; 
    7474it there's no selector, it's a leaf. Don't attempt to skip the if 
    7575statement: leaves don't have an empty list of branches, they don't have 
     
    9999of the attribute's name and distribution of classes. :obj:`Node`'s 
    100100branch description is, for all currently defined splits, an instance 
    101 of a class derived from :obj:`orange.Classifier` (in fact, it is 
    102 a :obj:`orange.ClassifierFromVarFD`, but a :obj:`orange.Classifier` 
    103 would suffice), and its :obj:`classVar` points to the attribute we seek. 
     101of a class derived from :obj:`Orange.classification.Classifier`  
     102(in fact, it is 
     103a :obj:`orange.ClassifierFromVarFD`, but a :obj:`Orange.classification.Classifier` 
     104would suffice), and its :obj:`class_var` points to the attribute we seek. 
    104105So we print its name. We will also assume that storing class distributions 
    105106has not been disabled and print them as well.  Then we iterate through 
     
    109110Finally, if the node is a leaf, we print out the distribution of learning 
    110111examples in the node and the class to which the examples in the node 
    111 would be classified. We again assume that the :obj:`nodeClassifier` is 
     112would be classified. We again assume that the :obj:`node_classifier` is 
    112113the default one - a :obj:`DefaultClassifier`. A better print function 
    113114should be aware of possible alternatives. 
     
    162163 
    163164There's nothing to prune at null-nodes or leaves, so we act only when 
    164 :obj:`node` and :obj:`node.branchSelector` are defined. If level is 
     165:obj:`node` and :obj:`node.branch_selector` are defined. If level is 
    165166not zero, we call the function for each branch. Otherwise, we clear the 
    166167selector, branches and branch descriptions. 
     
    217218We can now examine the default stopping parameters. 
    218219 
    219     >>> print learner.stop.maxMajority, learner.stop.minExamples 
     220    >>> print learner.stop.max_majority, learner.stop.min_examples 
    220221    1.0 0.0 
    221222 
     
    225226see what comes out. 
    226227 
    227     >>> learner.stop.minExamples = 5.0 
     228    >>> learner.stop.min_examples = 5.0 
    228229    >>> tree = learner(data) 
    229230    >>> print tree.dump() 
     
    241242the maximal proportion of majority class. 
    242243 
    243     >>> learner.stop.maxMajority = 0.5 
     244    >>> learner.stop.max_majority = 0.5 
    244245    >>> tree = learner(data) 
    245246    >>> print tree.dump() 
     
    271272        Stores a distribution for learning examples belonging to the 
    272273        node.  Storing distributions can be disabled by setting the 
    273         :obj:`_TreeLearner`'s storeDistributions flag to false. 
     274        :obj:`_TreeLearner`'s store_distributions flag to false. 
    274275 
    275276    .. attribute:: contingency 
     
    277278        Stores complete contingency matrices for the learning examples 
    278279        belonging to the node. Storing contingencies can be enabled by 
    279         setting :obj:`_TreeLearner`'s :obj:`storeContingencies` flag to 
     280        setting :obj:`_TreeLearner`'s :obj:`store_contingencies` flag to 
    280281        true. Note that even when the flag is not set, the contingencies 
    281282        get computed and stored to :obj:`Node`, but are removed shortly 
     
    290291        :obj:`Orange.data.Table` contain reference to examples in the 
    291292        root's :obj:`Orange.data.Table`. Examples are only stored if 
    292         a corresponding flag (:obj:`storeExamples`) has been set while 
     293        a corresponding flag (:obj:`store_examples`) has been set while 
    293294        building the tree; to conserve the space, storing is disabled 
    294295        by default. 
    295296 
    296     .. attribute:: nodeClassifier 
     297    .. attribute:: node_classifier 
    297298 
    298299        A classifier (usually, but not necessarily, a 
     
    301302        decide the final class (or class distribution) of an example. If 
    302303        it's an internal node, it is stored if :obj:`Node`'s flag 
    303         :obj:`storeNodeClassifier` is set. Since the :obj:`nodeClassifier` 
     304        :obj:`store_node_classifier` is set. Since the :obj:`node_classifier` 
    304305        is needed by :obj:`Descender` and for pruning (see far below), 
    305306        this is the default behaviour; space consumption of the default 
     
    315316        can be None; in this case the node is empty. 
    316317 
    317     .. attribute:: branchDescriptions 
     318    .. attribute:: branch_descriptions 
    318319 
    319320        A list with string descriptions for branches, constructed by 
     
    321322        descriptions, but basically, expect things like 'red' or '>12.3'. 
    322323 
    323     .. attribute:: branchSizes 
     324    .. attribute:: branch_sizes 
    324325 
    325326        Gives a (weighted) number of training examples that went into 
     
    327328        probabilities when classifying examples with unknown values. 
    328329 
    329     .. attribute:: branchSelector 
     330    .. attribute:: branch_selector 
    330331 
    331332        Gives a branch for each example. The same object is used 
    332         during learning and classifying. The :obj:`branchSelector` 
    333         is of type :obj:`orange.Classifier`, since its job is 
     333        during learning and classifying. The :obj:`branch_selector` 
     334        is of type :obj:`Orange.classification.Classifier`, since its job is 
    334335        similar to that of a classifier: it gets an example and 
    335336        returns discrete :obj:`Orange.data.Value` in range :samp:`[0, 
     
    338339        containing a special value (sVal) which should be a discrete 
    339340        distribution (DiscDistribution). This should represent a 
    340         :obj:`branchSelector`'s opinion of how to divide the example 
     341        :obj:`branch_selector`'s opinion of how to divide the example 
    341342        between the branches. Whether the proposition will be used or not 
    342343        depends upon the chosen :obj:`ExampleSplitter` (when learning) 
    343344        or :obj:`Descender` (when classifying). 
    344345 
    345     The lists :obj:`branches`, :obj:`branchDescriptions` and 
    346     :obj:`branchSizes` are of the same length; all of them are 
     346    The lists :obj:`branches`, :obj:`branch_descriptions` and 
     347    :obj:`branch_sizes` are of the same length; all of them are 
    347348    defined if the node is internal and none if it is a leaf. 
    348349 
    349     .. method:: treeSize() 
     350    .. method:: tree_size() 
    350351         
    351352        Return the number of nodes in the subtrees (including the node, 
     
    371372    and whose basic job is to descend as far down the tree as possible, 
    372373    according to the values of example's attributes. The :obj:`Descender`: 
    373     calls the node's :obj:`branchSelector` to get the branch index. If 
     374    calls the node's :obj:`branch_selector` to get the branch index. If 
    374375    it's a simple index, the corresponding branch is followed. If not, 
    375376    it's up to descender to decide what to do, and that's where descenders 
    376377    differ. A :obj:`descender` can choose a single branch (for instance, 
    377     the one that is the most recommended by the :obj:`branchSelector`) 
     378    the one that is the most recommended by the :obj:`branch_selector`) 
    378379    or it can let the branches vote. 
    379380 
     
    385386       selecting a single branch and continued the descend. In this case, 
    386387       the descender returns the reached :obj:`Node`. 
    387     #. :obj:`branchSelector` returned a distribution and the 
     388    #. :obj:`branch_selector` returned a distribution and the 
    388389       :obj:`Descender` decided to stop the descend at this (internal) 
    389390       node.  Again, descender returns the current :obj:`Node` and 
    390391       nothing else. 
    391     #. :obj:`branchSelector` returned a distribution and the 
     392    #. :obj:`branch_selector` returned a distribution and the 
    392393       :obj:`Node` wants to split the example (i.e., to decide the class 
    393394       by voting). 
     
    395396    It returns a :obj:`Node` and the vote-weights for the branches. 
    396397    The weights can correspond to the distribution returned by 
    397     :obj:`branchSelector`, to the number of learning examples that were 
     398    :obj:`branch_selector`, to the number of learning examples that were 
    398399    assigned to each branch, or to something else. 
    399400 
     
    402403    should stop; it does not matter whether it's a leaf (the first 
    403404    case above) or an internal node (the second case). The node's 
    404     :obj:`nodeClassifier` is used to decide the class. If the descender 
     405    :obj:`node_classifier` is used to decide the class. If the descender 
    405406    returns a :obj:`Node` and a distribution, the :obj:`TreeClassifier` 
    406407    recursively calls itself for each of the subtrees and the predictions 
     
    415416        It gets a :obj:`Node`, an :obj:`Orange.data.Instance` and a 
    416417        distribution of vote weights. For each node, it calls the 
    417         :obj:`classDistribution` and then multiplies and sums the 
     418        :obj:`class_distribution` and then multiplies and sums the 
    418419        distribution. :obj:`vote` returns a normalized distribution 
    419420        of predictions. 
    420421 
    421     .. method:: classDistribution() 
     422    .. method:: class_distribution() 
    422423 
    423424        Gets an additional parameter, a :obj:`Node` (default tree root). 
    424         :obj:`classDistribution` uses :obj:`descender`. If descender 
    425         reaches a leaf, it calls :obj:`nodeClassifier`, otherwise it 
     425        :obj:`class_distribution` uses :obj:`descender`. If descender 
     426        reaches a leaf, it calls :obj:`node_classifier`, otherwise it 
    426427        calls :obj:`vote`. 
    427428 
    428         Thus, the :obj:`vote` and :obj:`classDistribution` are written 
     429        Thus, the :obj:`vote` and :obj:`class_distribution` are written 
    429430        in a form of double recursion. The recursive calls do not happen 
    430431        at each node of the tree but only at nodes where a vote is needed 
     
    434435 
    435436        Calls the descender. If it reaches a leaf, the class is 
    436         predicted by the leaf's :obj:`nodeClassifier`. Otherwise, it calls 
    437         :obj:`vote`. From now on, :obj:`vote` and :obj:`classDistribution` 
     437        predicted by the leaf's :obj:`node_classifier`. Otherwise, it calls 
     438        :obj:`vote`. From now on, :obj:`vote` and :obj:`class_distribution` 
    438439        interweave down the tree and return a distribution of 
    439440        predictions. This method simply chooses the most probable class. 
     
    448449    Components that govern the structure of the tree are 
    449450    :obj:`split` (of type :obj:`SplitConstructor`), :obj:`stop` 
    450     (of type :obj:`StopCriteria` and :obj:`exampleSplitter` (of type 
     451    (of type :obj:`StopCriteria` and :obj:`example_splitter` (of type 
    451452    :obj:`ExampleSplitter`). 
    452453 
     
    459460        are binarized. Gain ratio is used to select attributes.  A minimum 
    460461        of two examples in a leaf is required for discreter and five 
    461         examples in a leaf for continuous attributes.</DD> 
     462        examples in a leaf for continuous attributes. 
    462463 
    463464    .. attribute:: stop 
     
    467468        the same class. 
    468469 
    469     .. attribute:: splitter 
     470    .. attribute:: example_splitter 
    470471 
    471472        Object of type :obj:`ExampleSplitter`. The default splitter is 
     
    473474        examples according to distributions given by the selector. 
    474475 
    475     .. attribute:: contingencyComputer 
     476    .. attribute:: contingency_computer 
    476477     
    477478        By default, this slot is left empty and ordinary contingency 
     
    484485        ignored by some splitting constructors. 
    485486 
    486     .. attribute:: nodeLearner 
     487    .. attribute:: node_learner 
    487488 
    488489        Induces a classifier from examples belonging to a 
    489490        node. The same learner is used for internal nodes 
    490         and for leaves. The default :obj:`nodeLearner` is 
     491        and for leaves. The default :obj:`node_learner` is 
    491492        :obj:`Orange.classification.majority.MajorityLearner`. 
    492493 
     
    495496        Descending component that the induces :obj:`TreeClassifier` will 
    496497        use. Default descender is :obj:`Descender_UnknownMergeAsSelector` 
    497         which votes using the :obj:`branchSelector`'s distribution for 
     498        which votes using the :obj:`branch_selector`'s distribution for 
    498499        vote weights. 
    499500 
    500     .. attribute:: maxDepth 
     501    .. attribute:: max_depth 
    501502 
    502503        Gives maximal tree depth; 0 means that only root is generated. 
     
    506507        this hard limit, you can do so as well. 
    507508 
    508     .. attribute:: storeDistributions, storeContingencies, storeExamples, storeNodeClassifier 
     509    .. attribute:: store_distributions, store_contingencies, store_examples, store_node_classifier 
    509510 
    510511        Decides whether to store class distributions, contingencies and 
    511         examples in :obj:`Node`, and whether the :obj:`nodeClassifier` 
     512        examples in :obj:`Node`, and whether the :obj:`node_classifier` 
    512513        should be build for internal nodes.  By default, distributions and 
    513514        node classifiers are stored, while contingencies and examples are 
     
    524525    examples are in a file or are fed through a filter, they are copied 
    525526    to a table. Even if they are already in a table, they are copied if 
    526     :obj:`storeExamples` is set. This is to assure that pointers remain 
     527    :obj:`store_examples` is set. This is to assure that pointers remain 
    527528    pointing to examples even if the user later changes the example 
    528     table. If they are in the table and the :obj:`storeExamples` flag 
     529    table. If they are in the table and the :obj:`store_examples` flag 
    529530    is clear, we just use them as they are. This will obviously crash 
    530531    in a multi-threaded system if one changes the table during the tree 
     
    543544 
    544545    The contingency matrix is computed next. This happens even if the flag 
    545     :obj:`storeContingencies` is false.  If the :obj:`contingencyComputer` 
     546    :obj:`store_contingencies` is false.  If the :obj:`contingency_computer` 
    546547    is given we use it, otherwise we construct just an ordinary 
    547548    contingency matrix. 
    548549 
    549550    A :obj:`stop` is called to see whether it's worth to continue. If 
    550     not, a :obj:`nodeClassifier` is built and the :obj:`Node` is 
    551     returned. Otherwise, a :obj:`nodeClassifier` is only built if 
     551    not, a :obj:`node_classifier` is built and the :obj:`Node` is 
     552    returned. Otherwise, a :obj:`node_classifier` is only built if 
    552553    :obj:`forceNodeClassifier` flag is set. 
    553554 
    554     To get a :obj:`Node`'s :obj:`nodeClassifier`, the 
    555     :obj:`nodeLearner`'s :obj:`smartLearn` function is called 
     555    To get a :obj:`Node`'s :obj:`node_classifier`, the 
     556    :obj:`node_learner`'s :obj:`smart_learn` function is called 
    556557    with the given examples, weight ID and the just computed 
    557558    matrix. If the learner can use the matrix (and the default, 
    558559    :obj:`Orange.classification.majority.MajorityLearner`, can), it won't 
    559     touch the examples. Thus, a choice of :obj:`contingencyComputer` 
    560     will, in many cases, affect the :obj:`nodeClassifier`. The 
    561     :obj:`nodeLearner` can return no classifier; if so and 
     560    touch the examples. Thus, a choice of :obj:`contingency_computer` 
     561    will, in many cases, affect the :obj:`node_classifier`. The 
     562    :obj:`node_learner` can return no classifier; if so and 
    562563    if the classifier would be needed for classification, 
    563564    the :obj:`TreeClassifier`'s function returns DK or an empty 
     
    573574 
    574575    The contingency gets removed at this point if it is not to be 
    575     stored. Thus, the :obj:`split`, :obj:`stop` and :obj:`exampleSplitter` 
     576    stored. Thus, the :obj:`split`, :obj:`stop` and :obj:`example_splitter` 
    576577    can use the contingency matrices if they will. 
    577578 
     
    615616    contingency computed from examples, apriori class probabilities, a 
    616617    list of candidate attributes it should consider and a node classifier 
    617     (if it was constructed, that is, if :obj:`storeNodeClassifier` 
     618    (if it was constructed, that is, if :obj:`store_node_classifier` 
    618619    is left true). 
    619620 
     
    629630    :obj:`SplitConstructor` returns most of the data we talked 
    630631    about when describing the :obj:`Node`. It returns a classifier 
    631     to be used as :obj:`Node`'s :obj:`branchSelector`, a list of branch 
     632    to be used as :obj:`Node`'s :obj:`branch_selector`, a list of branch 
    632633    descriptions and a list with the number of examples that go into 
    633634    each branch. Just what we need for the :obj:`Node`.  It can return 
     
    651652    by returning no classifier. This can happen for many reasons. 
    652653    A general one is related to number of examples in the branches. 
    653     :obj:`SplitConstructor` has a field :obj:`minSubset`, which sets 
     654    :obj:`SplitConstructor` has a field :obj:`min_subset`, which sets 
    654655    the minimal number of examples in a branch; null nodes, however, 
    655656    are allowed. If there is no split where this condition is met, 
    656657    :obj:`SplitConstructor` stops the induction. 
    657658 
    658     .. attribute:: minSubset 
     659    .. attribute:: min_subset 
    659660 
    660661        Sets the minimal number of examples in non-null leaves. As 
     
    664665    .. method:: __call__(examples, [weightID=0, apriori_distribution, candidates])  
    665666 
    666         Construct a split. Returns a tuple (:obj:`branchSelector`, 
    667         :obj:`branchDescriptions`, :obj:`subsetSizes`, :obj:`quality`, 
     667        Construct a split. Returns a tuple (:obj:`branch_selector`, 
     668        :obj:`branch_descriptions`, :obj:`subsetSizes`, :obj:`quality`, 
    668669        :obj:`spentAttribute`). :obj:`spentAttribute` is -1 if no 
    669670        attribute is completely spent by the split criterion. If no 
    670         split is constructed, the :obj:`selector`, :obj:`branchDescriptions` 
     671        split is constructed, the :obj:`selector`, :obj:`branch_descriptions` 
    671672        and :obj:`subsetSizes` are None, while :obj:`quality` is 0.0 and 
    672673        :obj:`spentAttribute` is -1. 
     
    678679            examples have a weight of 1.0.  
    679680        :param apriori-distribution: Should be of type  
    680             :obj:`orange.Distribution` and candidates should be a Python  
     681            :obj:`Orange.statistics.distribution.Distribution` and candidates should be a Python  
    681682            list of objects which are interpreted as booleans. 
    682683        :param candidates: The split constructor should consider only  
     
    704705        trees. 
    705706 
    706     .. attribute:: worstAcceptable 
     707    .. attribute:: worst_acceptable 
    707708 
    708709        The lowest required split quality for a split to be acceptable. 
     
    720721    highest score, one of them is selected by random. 
    721722 
    722     The constructed :obj:`branchSelector` is an instance of 
     723    The constructed :obj:`branch_selector` is an instance of 
    723724    :obj:`orange.ClassifierFromVarFD` that returns a value of the selected 
    724725    attribute. If the attribute is :obj:`Orange.data.variable.Discrete`, 
    725     :obj:`branchDescription`'s are the attribute's values. The attribute 
     726    :obj:`branch_description`'s are the attribute's values. The attribute 
    726727    is marked as spent, so that it cannot reappear in the node's subtrees. 
    727728 
     
    736737    it returns one of those with the highest score. 
    737738 
    738     The constructed :obj:`branchSelector` is again an instance 
     739    The constructed :obj:`branch_selector` is again an instance 
    739740    :obj:`orange.ClassifierFromVarFD` that returns a value of the 
    740741    selected attribute. This time, however, its :obj:`transformer` 
     
    758759    The attribute that yields the highest binary split is returned. 
    759760 
    760     The constructed :obj:`branchSelector` is again an instance 
     761    The constructed :obj:`branch_selector` is again an instance 
    761762    of :obj:`orange.ClassifierFromVarFD` with an attached 
    762763    :obj:`transformer`. This time, :obj:`transformer` is of type 
    763     :obj:`orange.ThresholdDiscretizer`. The branch descriptions are 
    764     "<threshold" and ">=threshold". The attribute is not spent. 
     764    :obj:`Orange.feature.discretization.ThresholdDiscretizer`. The branch 
     765    descriptions are "<threshold" and ">=threshold". The attribute is 
     766    not spent. 
    765767 
    766768.. class:: SplitConstructor_OneAgainstOthers 
     
    793795    simply choose the first attribute with the highest score anyway.) 
    794796 
    795     The :obj:`branchSelector`, :obj:`branchDescriptions` and whether 
     797    The :obj:`branch_selector`, :obj:`branch_descriptions` and whether 
    796798    the attribute is spent is decided by the winning split constructor. 
    797799 
    798     .. attribute: discreteSplitConstructor 
     800    .. attribute: discrete_split_constructor 
    799801 
    800802        Split constructor for discrete attributes; can be, 
     
    802804        :obj:`SplitConstructor_ExhaustiveBinary`. 
    803805 
    804     .. attribute: continuousSplitConstructor 
     806    .. attribute: continuous_split_constructor 
    805807 
    806808        Split constructor for continuous attributes; at the moment, it  
     
    808810        split constructor you programmed in Python. 
    809811 
    810     .. attribute: continuousSplitConstructor 
     812    .. attribute: continuous_split_constructor 
    811813     
    812814        Split constructor for continuous attributes; at the moment, 
     
    857859    examples. 
    858860 
    859     .. attribute:: maxMajor 
     861    .. attribute:: max_majority 
    860862 
    861863        Maximal proportion of majority class. When this is exceeded, 
    862864        induction stops. 
    863865 
    864     .. attribute:: minExamples 
     866    .. attribute:: min_examples 
    865867 
    866868        Minimal number of examples in internal leaves. Subsets with 
    867         less than :obj:`minExamples` examples are not split any further. 
     869        less than :obj:`min_examples` examples are not split any further. 
    868870        Example count is weighed. 
    869871 
     
    881883:obj:`ExampleSplitter` is given a :obj:`Node` (from which  
    882884it can use different stuff, but most of splitters only use the  
    883 :obj:`branchSelector`), a set of examples to be divided, and  
     885:obj:`branch_selector`), a set of examples to be divided, and  
    884886the weight ID. The result is a list of subsets of examples 
    885887and, optionally, a list of new weight ID's. 
    886888 
    887889Most :obj:`ExampleSplitter` classes simply call the node's 
    888 :obj:`branchSelector` and assign examples to corresponding branches. When 
     890:obj:`branch_selector` and assign examples to corresponding branches. When 
    889891the value is unknown they choose a particular branch or simply skip 
    890892the example. 
     
    917919         
    918920        Use the information in :obj:`node` (particularly the 
    919         :obj:`branchSelector`) to split the given set of examples into 
     921        :obj:`branch_selector`) to split the given set of examples into 
    920922        subsets.  Return a tuple with a list of example generators and 
    921923        a list of weights.  The list of weights is either an ordinary 
     
    10611063classifiers, branch selectors, ...  as the original tree. Thus, you may 
    10621064modify a pruned tree structure (manually cut it, add new nodes, replace 
    1063 components) but modifying, for instance, some node's :obj:`nodeClassifier` 
    1064 (a :obj:`nodeClassifier` itself, not a reference to it!) would modify 
    1065 the node's :obj:`nodeClassifier` in the corresponding node of the 
     1065components) but modifying, for instance, some node's :obj:`node_classifier` 
     1066(a :obj:`node_classifier` itself, not a reference to it!) would modify 
     1067the node's :obj:`node_classifier` in the corresponding node of the 
    10661068original tree. 
    10671069 
    1068 Pruners cannot construct a :obj:`nodeClassifier` nor merge 
    1069 :obj:`nodeClassifier` of the pruned subtrees into classifiers for new 
     1070Pruners cannot construct a :obj:`node_classifier` nor merge 
     1071:obj:`node_classifier` of the pruned subtrees into classifiers for new 
    10701072leaves. Thus, if you want to build a prunable tree, internal nodes 
    1071 must have their :obj:`nodeClassifier` defined. Fortunately, this is 
     1073must have their :obj:`node_classifier` defined. Fortunately, this is 
    10721074the default. 
    10731075 
     
    10961098 
    10971099    This pruner will only prune the nodes in which the node classifier  
    1098     is of class :obj:`orange.DefaultClassifier` (or from a derived class). 
     1100    is of class :obj:`Orange.classification.ConstantClassifier`  
     1101    (or from a derived class). 
    10991102 
    11001103    Note that the leaves with more than one majority class require some  
     
    12471250the node:: 
    12481251 
    1249     >>> print tree.dump(leafStr="%V (%M out of %N)") 
     1252    >>> print tree.dump(leaf_str="%V (%M out of %N)") 
    12501253    petal width<0.800: Iris-setosa (50.000 out of 50.000) 
    12511254    petal width>=0.800 
     
    12611264with this:: 
    12621265 
    1263     >>> print tree.dump(leafStr="%V (%^MbA%, %^MbP%)") 
     1266    >>> print tree.dump(leaf_str="%V (%^MbA%, %^MbP%)") 
    12641267    petal width<0.800: Iris-setosa (100%, 100%) 
    12651268    petal width>=0.800 
     
    13211324 
    13221325What is the order of numbers here? If you check  
    1323 :samp:`data.domain.classVar.values` , you'll learn that the order is setosa,  
     1326:samp:`data.domain.class_var.values` , you'll learn that the order is setosa,  
    13241327versicolor, virginica; so in the node at peta length<5.350 we have 49 
    13251328versicolors and 3 virginicae. To print out the proportions, we can 
     
    13421345:: 
    13431346 
    1344     tree.dump(leafStr="%V", nodeStr=".") 
     1347    tree.dump(leaf_str="%V", node_str=".") 
    13451348     
    1346 says that the nodeStr should be the same as leafStr (not very useful  
    1347 here, since leafStr is trivial anyway). 
     1349says that the node_str should be the same as leaf_str (not very useful  
     1350here, since leaf_str is trivial anyway). 
    13481351 
    13491352::  
     
    13661369of virginicas decreases down the tree:: 
    13671370 
    1368     print tree.dump(leafStr='%^.1CbA="Iris-virginica"% (%^.1CbP="Iris-virginica"%)', nodeStr='.') 
     1371    print tree.dump(leaf_str='%^.1CbA="Iris-virginica"% (%^.1CbP="Iris-virginica"%)', node_str='.') 
    13691372 
    13701373Let's first interpret the format string: :samp:`CbA="Iris-virginica"` is  
     
    14011404:: 
    14021405 
    1403     >>> print tree.dump(leafStr='"%V   %D %.2DbP %.2dbP"', nodeStr='"%D %.2DbP %.2dbP"') 
     1406    >>> print tree.dump(leaf_str='"%V   %D %.2DbP %.2dbP"', node_str='"%D %.2DbP %.2dbP"') 
    14041407    root: [50.000, 50.000, 50.000] . . 
    14051408    |    petal width<0.800: [50.000, 0.000, 0.000] [1.00, 0.00, 0.00] [3.00, 0.00, 0.00]: 
     
    14391442the 90% confidence intervals in the leaves:: 
    14401443 
    1441     >>> print tree.dump(leafStr="[SE: %E]\t %V %I(90)", nodeStr="[SE: %E]") 
     1444    >>> print tree.dump(leaf_str="[SE: %E]\t %V %I(90)", node_str="[SE: %E]") 
    14421445    root: [SE: 0.409] 
    14431446    |    RM<6.941: [SE: 0.306] 
     
    14671470:samp:`%A` the average? Doesn't a regression tree always predict the 
    14681471leaf average anyway? Not necessarily, the tree predict whatever the 
    1469 :attr:`TreeClassifier.nodeClassifier` in a leaf returns.  
     1472:attr:`TreeClassifier.node_classifier` in a leaf returns.  
    14701473As :samp:`%V` uses the :obj:`Orange.data.variable.Continuous`' function 
    14711474for printing out the value, therefore the printed number has the same 
     
    14781481this number with values in the parent nodes:: 
    14791482 
    1480     >>> print tree.dump(leafStr="%C<22 (%cbP<22)", nodeStr=".") 
     1483    >>> print tree.dump(leaf_str="%C<22 (%cbP<22)", node_str=".") 
    14811484    root: 277.000 (.) 
    14821485    |    RM<6.941: 273.000 (1.160) 
     
    15051508:: 
    15061509 
    1507     >>> print tree.dump(leafStr="%C![20,22] (%^cbP![20,22]%)", nodeStr=".") 
     1510    >>> print tree.dump(leaf_str="%C![20,22] (%^cbP![20,22]%)", node_str=".") 
    15081511 
    15091512OK, let's observe the format string for one last time. :samp:`%c![20, 
     
    15351538------------------------------------ 
    15361539 
    1537 :meth:`TreeClassifier.dump`'s argument :obj:`userFormats` can be used to print out 
     1540:meth:`TreeClassifier.dump`'s argument :obj:`user_formats` can be used to print out 
    15381541some other information in the leaves or nodes. If provided, 
    1539 :obj:`userFormats` should contain a list of tuples with a regular 
     1542:obj:`user_formats` should contain a list of tuples with a regular 
    15401543expression and a callback function to be called when that expression 
    1541 is found in the format string. Expressions from :obj:`userFormats` 
     1544is found in the format string. Expressions from :obj:`user_formats` 
    15421545are checked before the built-in expressions discussed above, so you can 
    15431546override the built-ins if you want to. 
     
    15451548The regular expression should describe a string like those we used above, 
    15461549for instance the string :samp:`%.2DbP`. When a leaf or internal node 
    1547 is printed out, the format string (:obj:`leafStr` or :obj:`nodeStr`) 
     1550is printed out, the format string (:obj:`leaf_str` or :obj:`node_str`) 
    15481551is checked for these regular expressions and when the match is found, 
    15491552the corresponding callback function is called. 
    15501553 
    15511554The callback function will get five arguments: the format string  
    1552 (:obj:`leafStr` or :obj:`nodeStr`), the match object, the node which is 
     1555(:obj:`leaf_str` or :obj:`node_str`), the match object, the node which is 
    15531556being printed, its parent (can be None) and the tree classifier. 
    15541557The function should return the format string in which the part described 
     
    15831586 
    15841587    def replaceV(strg, mo, node, parent, tree): 
    1585         return insertStr(strg, mo, str(node.nodeClassifier.defaultValue)) 
     1588        return insertStr(strg, mo, str(node.node_classifier.default_value)) 
    15861589 
    15871590It therefore takes the value predicted at the node 
    1588 (:samp:`node.nodeClassifier.defaultValue` ), converts it to a string 
     1591(:samp:`node.node_classifier.default_value` ), converts it to a string 
    15891592and passes it to *insertStr* to do the replacement. 
    15901593 
     
    17271730    Quinlan's C4.5 code. 
    17281731 
    1729     .. attribute:: nodeType 
     1732    .. attribute:: node_type 
    17301733 
    17311734        Type of the node:  :obj:`C45Node.Leaf` (0),  
     
    17461749        Number of (learning) examples in the node. 
    17471750 
    1748     .. attribute:: classDist 
     1751    .. attribute:: class_dist 
    17491752 
    17501753        Class distribution for the node (of type  
    1751         :obj:`orange.DiscDistribution`). 
     1754        :obj:`Orange.statistics.distribution.Discrete`). 
    17521755 
    17531756    .. attribute:: tested 
     
    18141817in :samp:`node.leaf`. Since this is not a qualified value (ie.,  
    18151818:obj:`C45Node` does not know to which attribute it belongs), we need to 
    1816 convert it to a string through :obj:`classVar`, which is passed as an 
     1819convert it to a string through :obj:`class_var`, which is passed as an 
    18171820extra argument to the recursive part of printTree. 
    18181821 
     
    20652068 
    20662069        """ 
    2067         return  _c45_printTree0(self.tree, self.classVar, 0) 
     2070        return  _c45_printTree0(self.tree, self.class_var, 0) 
    20682071 
    20692072def _c45_showBranch(node, classvar, lev, i): 
    20702073    var = node.tested 
    20712074    str_ = "" 
    2072     if node.nodeType == 1: 
     2075    if node.node_type == 1: 
    20732076        str_ += "\n"+"|   "*lev + "%s = %s:" % (var.name, var.values[i]) 
    20742077        str_ += _c45_printTree0(node.branch[i], classvar, lev+1) 
    2075     elif node.nodeType == 2: 
     2078    elif node.node_type == 2: 
    20762079        str_ += "\n"+"|   "*lev + "%s %s %.1f:" % (var.name, ["<=", ">"][i], node.cut) 
    20772080        str_ += _c45_printTree0(node.branch[i], classvar, lev+1) 
     
    20902093    var = node.tested 
    20912094    str_ = "" 
    2092     if node.nodeType == 0: 
     2095    if node.node_type == 0: 
    20932096        str_ += "%s (%.1f)" % (classvar.values[int(node.leaf)], node.items)  
    20942097    else: 
    20952098        for i, branch in enumerate(node.branch): 
    2096             if not branch.nodeType: 
     2099            if not branch.node_type: 
    20972100                str_ += _c45_showBranch(node, classvar, lev, i) 
    20982101        for i, branch in enumerate(node.branch): 
    2099             if branch.nodeType: 
     2102            if branch.node_type: 
    21002103                str_ += _c45_showBranch(node, classvar, lev, i) 
    21012104    return str_ 
    21022105 
    21032106def _printTreeC45(tree): 
    2104     print _c45_printTree0(tree.tree, tree.classVar, 0) 
     2107    print _c45_printTree0(tree.tree, tree.class_var, 0) 
    21052108 
    21062109 
     
    21192122    of :class:`TreeClassifier` object is returned instead. 
    21202123 
    2121     The values of attributes can be also be set in the constructor.  
    2122  
    2123     .. attribute:: nodeLearner 
     2124    Attributes can be also be set in the constructor.  
     2125 
     2126    .. attribute:: node_learner 
    21242127 
    21252128        Induces a classifier from examples belonging to a node. The 
    21262129        same learner is used for internal nodes and for leaves. The 
    2127         default :obj:`nodeLearner` is :obj:`Orange.classification.majority.MajorityLearner`. 
     2130        default is :obj:`Orange.classification.majority.MajorityLearner`. 
    21282131 
    21292132    **Split construction** 
     
    21372140        affect the procedures for growing of the tree are ignored. These 
    21382141        include :obj:`binarization`, :obj:`measure`, 
    2139         :obj:`worstAcceptable` and :obj:`minSubset` (Default: 
     2142        :obj:`worst_acceptable` and :obj:`min_subset` (Default: 
    21402143        :class:SplitConstructor_Combined  
    21412144        with separate constructors for discrete and continuous attributes. 
     
    21642167        "retis" (:class:`Orange.feature.scoring.MSE`). Default: "gainRatio". 
    21652168 
    2166     .. attribute:: reliefM, reliefK 
     2169    .. attribute:: relief_m, relief_k 
    21672170 
    21682171        Sem `m` and `k` to given values if the :obj:`measure` is relief. 
     
    21772180    **Pruning** 
    21782181 
    2179     .. attribute:: worstAcceptable 
     2182    .. attribute:: worst_acceptable 
    21802183 
    21812184        Used in pre-pruning, sets the lowest required attribute 
     
    21832186        tree at that node is not grown further (default: 0). 
    21842187 
    2185         So, to allow splitting only when gainRatio (the default measure) 
    2186         is greater than 0.6, set :samp:`worstAcceptable=0.6`. 
    2187  
    2188     .. attribute:: minSubset 
     2188        So, to allow splitting only when gain ratio (the default measure) 
     2189        is greater than 0.6, set :samp:`worst_acceptable=0.6`. 
     2190 
     2191    .. attribute:: min_subset 
    21892192 
    21902193        Minimal number of examples in non-null leaves (default: 0). 
    21912194 
    2192     .. attribute:: minExamples 
    2193  
    2194         Data subsets with less than :obj:`minExamples` 
     2195    .. attribute:: min_examples 
     2196 
     2197        Data subsets with less than :obj:`min_examples` 
    21952198        examples are not split any further, that is, all leaves in the tree 
    21962199        will contain at least that many of examples (default: 0). 
    21972200 
    2198     .. attribute:: maxDepth 
     2201    .. attribute:: max_depth 
    21992202 
    22002203        Gives maximal tree depth;  0 means that only root is generated.  
    22012204        The default is 100.  
    22022205 
    2203     .. attribute:: maxMajority 
     2206    .. attribute:: max_majority 
    22042207 
    22052208        Induction stops when the proportion of majority class in the 
    22062209        node exceeds the value set by this parameter(default: 1.0).  
    22072210        To stop the induction as soon as the majority class reaches 70%, 
    2208         you should use :samp:`maxMajority=0.7`, as in the following 
     2211        you should use :samp:`max_majority=0.7`, as in the following 
    22092212        example. The numbers show the majority class  
    22102213        proportion at each node. The script `tree2.py`_ induces and  
     
    22272230        tree induction algorithms. See a documentation on  
    22282231        :class:`StopCriteria` for more info on this function.  
    2229         When used, parameters  :obj:`maxMajority` and :obj:`minExamples`  
     2232        When used, parameters  :obj:`max_majority` and :obj:`min_examples`  
    22302233        will not be  considered (default: None).  
    22312234        The default stopping criterion stops induction when all examples  
     
    22462249    **Record keeping** 
    22472250 
    2248     .. attribute:: storeDistributions, storeContingencies, storeExamples, storeNodeClassifier 
     2251    .. attribute:: store_distributions, store_contingencies, store_examples, store_node_classifier 
    22492252 
    22502253        Determines whether to store class distributions, contingencies and 
    2251         examples in :class:`Node`, and whether the :obj:`nodeClassifier` 
     2254        examples in :class:`Node`, and whether the :obj:`node_classifier` 
    22522255        should be build for internal nodes. By default everything except  
    2253         :obj:`storeExamples` is enabled. You won't save any memory by not storing  
     2256        :obj:`store_examples` is enabled. You won't save any memory by not storing  
    22542257        distributions but storing contingencies, since distributions actually points to 
    22552258        the same distribution that is stored in 
    22562259        :obj:`contingency.classes`. (default: True except for 
    2257         storeExamples, which defaults to False). 
     2260        store_examples, which defaults to False). 
    22582261     
    22592262    """ 
     
    22962299        if not self._handset_split and not self.measure: 
    22972300            measure = fscoring.GainRatio() \ 
    2298                 if examples.domain.classVar.varType == Orange.data.Type.Discrete \ 
     2301                if examples.domain.class_var.var_type == Orange.data.Type.Discrete \ 
    22992302                else fscoring.MSE() 
    2300             bl.split.continuousSplitConstructor.measure = measure 
    2301             bl.split.discreteSplitConstructor.measure = measure 
     2303            bl.split.continuous_split_constructor.measure = measure 
     2304            bl.split.discrete_split_constructor.measure = measure 
    23022305          
    23032306        if self.splitter != None: 
     
    23482351        """ 
    23492352        split = SplitConstructor_Combined() 
    2350         split.continuousSplitConstructor = \ 
     2353        split.continuous_split_constructor = \ 
    23512354            SplitConstructor_Threshold() 
    23522355        binarization = getattr(self, "binarization", 0) 
    23532356        if binarization == 1: 
    2354             split.discreteSplitConstructor = \ 
     2357            split.discrete_split_constructor = \ 
    23552358                SplitConstructor_ExhaustiveBinary() 
    23562359        elif binarization == 2: 
    2357             split.discreteSplitConstructor = \ 
     2360            split.discrete_split_constructor = \ 
    23582361                SplitConstructor_OneAgainstOthers() 
    23592362        else: 
    2360             split.discreteSplitConstructor = \ 
     2363            split.discrete_split_constructor = \ 
    23612364                SplitConstructor_Feature() 
    23622365 
     
    23752378 
    23762379        measureIsRelief = isinstance(measure, fscoring.Relief) 
    2377         relM = getattr(self, "reliefM", None) 
     2380        relM = getattr(self, "relief_m", None) 
    23782381        if relM and measureIsRelief: 
    23792382            measure.m = relM 
    23802383         
    2381         relK = getattr(self, "reliefK", None) 
     2384        relK = getattr(self, "relief_k", None) 
    23822385        if relK and measureIsRelief: 
    23832386            measure.k = relK 
    23842387 
    2385         split.continuousSplitConstructor.measure = measure 
    2386         split.discreteSplitConstructor.measure = measure 
    2387  
    2388         wa = getattr(self, "worstAcceptable", 0) 
     2388        split.continuous_split_constructor.measure = measure 
     2389        split.discrete_split_constructor.measure = measure 
     2390 
     2391        wa = getattr(self, "worst_acceptable", 0) 
    23892392        if wa: 
    2390             split.continuousSplitConstructor.worstAcceptable = wa 
    2391             split.discreteSplitConstructor.worstAcceptable = wa 
    2392  
    2393         ms = getattr(self, "minSubset", 0) 
     2393            split.continuous_split_constructor.worst_acceptable = wa 
     2394            split.discrete_split_constructor.worst_acceptable = wa 
     2395 
     2396        ms = getattr(self, "min_subset", 0) 
    23942397        if ms: 
    2395             split.continuousSplitConstructor.minSubset = ms 
    2396             split.discreteSplitConstructor.minSubset = ms 
     2398            split.continuous_split_constructor.min_subset = ms 
     2399            split.discrete_split_constructor.min_subset = ms 
    23972400 
    23982401        return split 
     
    24032406        """ 
    24042407        stop = Orange.classification.tree.StopCriteria_common() 
    2405         mm = getattr(self, "maxMajority", 1.0) 
     2408        mm = getattr(self, "max_majority", 1.0) 
    24062409        if mm < 1.0: 
    2407             stop.maxMajority = self.maxMajority 
    2408         me = getattr(self, "minExamples", 0) 
     2410            stop.max_majority = self.max_majority 
     2411        me = getattr(self, "min_examples", 0) 
    24092412        if me: 
    2410             stop.minExamples = self.minExamples 
     2413            stop.min_examples = self.min_examples 
    24112414        return stop 
    24122415 
     
    24172420        learner.stop = self.stop 
    24182421 
    2419         for a in ["storeDistributions", "storeContingencies", "storeExamples",  
    2420             "storeNodeClassifier", "nodeLearner", "maxDepth"]: 
     2422        for a in ["store_distributions", "store_contingencies", "store_examples",  
     2423            "store_node_classifier", "node_learner", "max_depth"]: 
    24212424            if hasattr(self, a): 
    24222425                setattr(learner, a, getattr(self, a)) 
     
    24252428 
    24262429    _built_fn = {  
    2427             "split": [ _build_split, [ "binarization", "measure", "reliefM", "reliefK", "worstAcceptable", "minSubset" ] ], \ 
    2428             "stop": [ _build_stop, ["maxMajority", "minExamples" ] ]  
     2430            "split": [ _build_split, [ "binarization", "measure", "relief_m", "relief_k", "worst_acceptable", "min_subset" ] ], \ 
     2431            "stop": [ _build_stop, ["max_majority", "min_examples" ] ]  
    24292432        } 
    24302433 
     
    24332436TreeLearner = Orange.misc.deprecated_members({ 
    24342437          "mForPruning": "m_pruning", 
    2435           "sameMajorityPruning": "same_majority_pruning" 
     2438          "sameMajorityPruning": "same_majority_pruning", 
     2439          "reliefM": "relief_m", 
     2440          "reliefK": "relief_k", 
     2441          "storeDistributions": "store_distributions", 
     2442          "storeContingencies": "store_contingencies", 
     2443          "storeExamples": "store_examples", 
     2444          "storeNodeClassifier": "store_node_classifier", 
     2445          "worstAcceptable": "worst_acceptable", 
     2446          "minSubset": "min_subset", 
     2447          "maxMajority": "max_majority", 
     2448          "minExamples": "min_examples", 
     2449          "maxDepth": "max_depth", 
     2450          "nodeLearner": "node_learner" 
    24362451}, wrap_methods=[])(TreeLearner) 
    24372452 
     
    25102525 
    25112526def replaceV(strg, mo, node, parent, tree): 
    2512     return insertStr(strg, mo, str(node.nodeClassifier.defaultValue)) 
     2527    return insertStr(strg, mo, str(node.node_classifier.default_value)) 
    25132528 
    25142529def replaceN(strg, mo, node, parent, tree): 
     
    25272542def replaceM(strg, mo, node, parent, tree): 
    25282543    by = mo.group("by") 
    2529     maj = int(node.nodeClassifier.defaultValue) 
     2544    maj = int(node.node_classifier.default_value) 
    25302545    N = node.distribution[maj] 
    25312546    if by: 
     
    25412556def replacem(strg, mo, node, parent, tree): 
    25422557    by = mo.group("by") 
    2543     maj = int(node.nodeClassifier.defaultValue) 
     2558    maj = int(node.node_classifier.default_value) 
    25442559    if node.distribution.abs > 1e-30: 
    25452560        N = node.distribution[maj] / node.distribution.abs 
     
    25572572 
    25582573def replaceCdisc(strg, mo, node, parent, tree): 
    2559     if tree.classVar.varType != Orange.data.Type.Discrete: 
     2574    if tree.class_var.var_type != Orange.data.Type.Discrete: 
    25602575        return insertDot(strg, mo) 
    25612576     
     
    25752590     
    25762591def replacecdisc(strg, mo, node, parent, tree): 
    2577     if tree.classVar.varType != Orange.data.Type.Discrete: 
     2592    if tree.class_var.var_type != Orange.data.Type.Discrete: 
    25782593        return insertDot(strg, mo) 
    25792594     
     
    25972612 
    25982613def replaceCcont(strg, mo, node, parent, tree): 
    2599     if tree.classVar.varType != Orange.data.Type.Continuous: 
     2614    if tree.class_var.var_type != Orange.data.Type.Continuous: 
    26002615        return insertDot(strg, mo) 
    26012616     
     
    26172632     
    26182633def replaceccont(strg, mo, node, parent, tree): 
    2619     if tree.classVar.varType != Orange.data.Type.Continuous: 
     2634    if tree.class_var.var_type != Orange.data.Type.Continuous: 
    26202635        return insertDot(strg, mo) 
    26212636     
     
    26512666     
    26522667def replaceCconti(strg, mo, node, parent, tree): 
    2653     if tree.classVar.varType != Orange.data.Type.Continuous: 
     2668    if tree.class_var.var_type != Orange.data.Type.Continuous: 
    26542669        return insertDot(strg, mo) 
    26552670 
     
    26692684             
    26702685def replacecconti(strg, mo, node, parent, tree): 
    2671     if tree.classVar.varType != Orange.data.Type.Continuous: 
     2686    if tree.class_var.var_type != Orange.data.Type.Continuous: 
    26722687        return insertDot(strg, mo) 
    26732688 
     
    26912706     
    26922707def replaceD(strg, mo, node, parent, tree): 
    2693     if tree.classVar.varType != Orange.data.Type.Discrete: 
     2708    if tree.class_var.var_type != Orange.data.Type.Discrete: 
    26942709        return insertDot(strg, mo) 
    26952710 
     
    27102725 
    27112726def replaced(strg, mo, node, parent, tree): 
    2712     if tree.classVar.varType != Orange.data.Type.Discrete: 
     2727    if tree.class_var.var_type != Orange.data.Type.Discrete: 
    27132728        return insertDot(strg, mo) 
    27142729 
     
    27322747 
    27332748def replaceAE(strg, mo, node, parent, tree): 
    2734     if tree.classVar.varType != Orange.data.Type.Continuous: 
     2749    if tree.class_var.var_type != Orange.data.Type.Continuous: 
    27352750        return insertDot(strg, mo) 
    27362751 
     
    27612776 
    27622777def replaceI(strg, mo, node, parent, tree): 
    2763     if tree.classVar.varType != Orange.data.Type.Continuous: 
     2778    if tree.class_var.var_type != Orange.data.Type.Continuous: 
    27642779        return insertDot(strg, mo) 
    27652780 
     
    28032818            self.leafStr = leafStr 
    28042819        else: 
    2805             if self.node().node_classifier.classVar.varType == \ 
     2820            if self.node().node_classifier.class_var.var_type == \ 
    28062821                    Orange.data.Type.Discrete: 
    28072822                self.leafStr = "%V (%^.2m%)" 
     
    28382853 
    28392854    def showBranch(self, node, parent, lev, i): 
    2840         bdes = node.branchDescriptions[i] 
    2841         bdes = node.branchSelector.classVar.name + \ 
     2855        bdes = node.branch_descriptions[i] 
     2856        bdes = node.branch_selector.class_var.name + \ 
    28422857            (bdes[0] not in "<=>" and "=" or "") + bdes 
    28432858        if node.branches[i]: 
     
    29072922                return 
    29082923                 
    2909             label = node.branchSelector.classVar.name 
     2924            label = node.branch_selector.class_var.name 
    29102925            if self.nodeStr: 
    29112926                label += "\\n" + self.formatString(self.nodeStr, node, parent) 
     
    29192934                        (_quoteName(internalName),  
    29202935                         _quoteName(internalBranchName),  
    2921                          node.branchDescriptions[i])) 
     2936                         node.branch_descriptions[i])) 
    29222937                    self.dotTree0(branch, node, internalBranchName) 
    29232938                     
     
    29742989        return self.dump() 
    29752990 
    2976     def dump(self, leafStr = "", nodeStr = "", **argkw):   
     2991    @Orange.misc.deprecated_keywords({"fileName": "file_name", \ 
     2992        "leafStr": "leaf_str", "nodeStr": "node_str", \ 
     2993        "userFormats": "user_formats", "minExamples": "min_examples", \ 
     2994        "maxDepth": "max_depth", "simpleFirst": "simple_first"}) 
     2995    def dump(self, leaf_str = "", node_str = "", \ 
     2996            user_formats=[], min_examples=0, max_depth=1e10, \ 
     2997            simple_first=True): 
    29772998        """ 
    29782999        Return a string representation of a tree. 
    29793000 
    2980         :arg leafStr: The format string for printing the tree leaves. If  
     3001        :arg leaf_str: The format string for printing the tree leaves. If  
    29813002          left empty, "%V (%^.2m%)" will be used for classification trees 
    29823003          and "%V" for regression trees. 
    2983         :type leafStr: string 
    2984         :arg nodeStr: The format string for printing out the internal nodes. 
     3004        :type leaf_str: string 
     3005        :arg node_str: The format string for printing out the internal nodes. 
    29853006          If left empty (as it is by default), no data is printed out for 
    29863007          internal nodes. If set to :samp:`"."`, the same string is 
    29873008          used as for leaves. 
    2988         :type nodeStr: string 
    2989         :arg maxDepth: If set, it limits the depth to which the tree is 
     3009        :type node_str: string 
     3010        :arg max_depth: If set, it limits the depth to which the tree is 
    29903011          printed out. 
    2991         :type maxDepth: integer 
    2992         :arg minExamples: If set, the subtrees with less than the given  
     3012        :type max_depth: integer 
     3013        :arg min_examples: If set, the subtrees with less than the given  
    29933014          number of examples are not printed. 
    2994         :type minExamples: integer 
    2995         :arg simpleFirst: If True (default), the branches with a single  
     3015        :type min_examples: integer 
     3016        :arg simple_first: If True (default), the branches with a single  
    29963017          node are printed before the branches with larger subtrees.  
    29973018          If False, the branches are printed in order of 
    29983019          appearance. 
    2999         :type simpleFirst: boolean 
    3000         :arg userFormats: A list of regular expressions and callback  
     3020        :type simple_first: boolean 
     3021        :arg user_formats: A list of regular expressions and callback  
    30013022          function through which the user can print out other specific  
    30023023          information in the nodes. 
    30033024        """ 
    3004         return _TreeDumper(leafStr, nodeStr, argkw.get("userFormats", []) +  
    3005             _TreeDumper.defaultStringFormats, argkw.get("minExamples", 0),  
    3006             argkw.get("maxDepth", 1e10), argkw.get("simpleFirst", True), 
    3007             self).dumpTree() 
    3008  
    3009     def dot(self, fileName, leafStr = "", nodeStr = "", leafShape="plaintext", nodeShape="plaintext", **argkw): 
     3025        return _TreeDumper(leaf_str, node_str, user_formats +  
     3026            _TreeDumper.defaultStringFormats, min_examples,  
     3027            max_depth, simple_first, self).dumpTree() 
     3028 
     3029    @Orange.misc.deprecated_keywords({"fileName": "file_name", \ 
     3030        "leafStr": "leaf_str", "nodeStr": "node_str", \ 
     3031        "leafShape": "leaf_shape", "nodeShape": "node_shape", \ 
     3032        "userFormats": "user_formats", "minExamples": "min_examples", \ 
     3033        "maxDepth": "max_depth", "simpleFirst": "simple_first"}) 
     3034    def dot(self, fileName, leaf_str = "", node_str = "", \ 
     3035            leaf_shape="plaintext", node_shape="plaintext", \ 
     3036            user_formats=[], min_examples=0, max_depth=1e10, \ 
     3037            simple_first=True): 
    30103038        """ Print the tree to a file in a format used by  
    30113039        `GraphViz <http://www.research.att.com/sw/tools/graphviz>`_. 
     
    30143042        nodes and leaves of the tree: 
    30153043 
    3016         :param leafShape: Shape of the outline around leaves of the tree.  
     3044        :param leaf_shape: Shape of the outline around leaves of the tree.  
    30173045            If "plaintext", no outline is used (default: "plaintext"). 
    3018         :type leafShape: string 
    3019         :param internalNodeShape: Shape of the outline around internal nodes  
    3020             of the tree. If "plaintext", no outline is used (default: "box") 
    3021         :type leafShape: string 
     3046        :type leaf_shape: string 
     3047        :param node_shape: Shape of the outline around internal nodes  
     3048            of the tree. If "plaintext", no outline is used (default: "plaintext") 
     3049        :type node_shape: string 
    30223050 
    30233051        Check `Polygon-based Nodes <http://www.graphviz.org/doc/info/shapes.html>`_  
     
    30263054        fle = type(fileName) == str and open(fileName, "wt") or fileName 
    30273055 
    3028         _TreeDumper(leafStr, nodeStr, argkw.get("userFormats", []) +  
    3029             _TreeDumper.defaultStringFormats, argkw.get("minExamples", 0),  
    3030             argkw.get("maxDepth", 1e10), argkw.get("simpleFirst", True), self, 
    3031             leafShape=leafShape, nodeShape=nodeShape, fle=fle).dotTree() 
     3056        _TreeDumper(leaf_str, node_str, user_formats +  
     3057            _TreeDumper.defaultStringFormats, min_examples,  
     3058            max_depth, simple_first, self, 
     3059            leafShape=leaf_shape, nodeShape=node_shape, fle=fle).dotTree() 
    30323060 
    30333061    def count_nodes(self): 
  • orange/Orange/data/io.py

    r9450 r9483  
    260260    attributeLoadStatus = {} 
    261261    def make_float(name): 
    262         attr, s = orange.Variable.make(name, orange.VarTypes.Continuous, [], [], createOnNew) 
     262        attr, s = Orange.data.variable.make(name, Orange.data.Type.Continuous, [], [], create_on_new) 
    263263        attributeLoadStatus[attr] = s 
    264264        return attr 
    265265     
    266266    def make_disc(name, unordered): 
    267         attr, s = orange.Variable.make(name, orange.VarTypes.Discrete, [], unordered, createOnNew) 
     267        attr, s = Orange.data.variable.make(name, Orange.data.Type.Discrete, [], unordered, create_on_new) 
    268268        attributeLoadStatus[attr] = s 
    269269        return attr 
     
    279279    attributeLoadStatus = [attributeLoadStatus[attr] for attr in attributes] + \ 
    280280                          [attributeLoadStatus[classVar]] 
    281     domain = orange.Domain(attributes, classVar) 
    282     table = orange.ExampleTable([orange.Example(domain, [ex.get(attr, attr("?")) for attr in attributes] + [c]) for ex, c in zip(values, classes)]) 
     281    domain = Orange.data.Domain(attributes, classVar) 
     282    table = Orange.data.Table([Orange.data.Instance(domain, [ex.get(attr, attr("?")) for attr in attributes] + [c]) for ex, c in zip(values, classes)]) 
    283283    table.attribute_load_status = attributeLoadStatus 
    284284    return table 
  • orange/Orange/distance/instances.py

    r8059 r8123  
    347347        res = diff * self.icm * diff.transpose() 
    348348        return res[0,0]**0.5 
     349     
     350     
     351class PearsonRAbsoluteConstructor(PearsonRConstructor): 
     352    """ Construct an instance of PearsonRAbsolute example distance estimator. 
     353    """ 
     354    def __call__(self, data): 
     355        indxs = [i for i, a in enumerate(data.domain.attributes) \ 
     356                 if a.varType==Orange.data.Type.Continuous] 
     357        return PearsonRAbsolute(domain=data.domain, indxs=indxs) 
     358     
     359     
     360class PearsonRAbsolute(PearsonR): 
     361    """ An example distance estimator using absolute value of Pearson 
     362    correlation coefficient. 
     363    """ 
     364    def __call__(self, e1, e2): 
     365        """ 
     366        Return absolute Pearson's dissimilarity between e1 and e2, 
     367        i.e. 
     368         
     369        .. math:: (1 - abs(r))/2 
     370         
     371        where r is Pearson's correlation coefficient. 
     372        """ 
     373        X1 = []; X2 = [] 
     374        for i in self.indxs: 
     375            if not(e1[i].isSpecial() or e2[i].isSpecial()): 
     376                X1.append(float(e1[i])) 
     377                X2.append(float(e2[i])) 
     378        if not X1: 
     379            return 1.0 
     380        try: 
     381            return (1.0 - abs(statc.pearsonr(X1, X2)[0])) 
     382        except: 
     383            return 1.0 
     384         
     385         
     386class SpearmanRAbsoluteConstructor(SpearmanRConstructor): 
     387    """ Construct an instance of SpearmanRAbsolute example distance estimator. 
     388    """ 
     389    def __call__(self, data): 
     390        indxs = [i for i, a in enumerate(data.domain.attributes) \ 
     391                 if a.varType==Orange.data.Type.Continuous] 
     392        return SpearmanRAbsolute(domain=data.domain, indxs=indxs) 
     393     
     394     
     395class SpearmanRAbsolute(SpearmanR): 
     396    def __call__(self, e1, e2): 
     397        """ 
     398        Return absolute Spearman's dissimilarity between e1 and e2, 
     399        i.e. 
     400          
     401        .. math:: (1 - abs(r))/2 
     402         
     403        where r is Spearman's correlation coefficient. 
     404        """ 
     405        X1 = []; X2 = [] 
     406        for i in self.indxs: 
     407            if not(e1[i].isSpecial() or e2[i].isSpecial()): 
     408                X1.append(float(e1[i])) 
     409                X2.append(float(e2[i])) 
     410        if not X1: 
     411            return 1.0 
     412        try: 
     413            return (1.0 - abs(statc.spearmanr(X1, X2)[0])) 
     414        except: 
     415            return 1.0 
     416     
     417     
     418def distance_matrix(data, distance_constructor, progress_callback=None): 
     419    """ A helper function that computes an obj:`Orange.core.SymMatrix` of all 
     420    pairwise distances between instances in `data`. 
     421     
     422    :param data: A data table 
     423    :type data: :obj:`Orange.data.Table` 
     424     
     425    :param distance_constructor: An ExamplesDistance_Constructor instance. 
     426    :type distance_constructor: :obj:`Orange.distances.ExampleDistConstructor` 
     427     
     428    """ 
     429    from Orange.misc import progressBarMilestones as progress_milestones 
     430    matrix = Orange.core.SymMatrix(len(data)) 
     431    dist = distance_constructor(data) 
     432     
     433    msize = len(data)*(len(data) - 1)/2 
     434    milestones = progress_milestones(msize, 100) 
     435    count = 0 
     436    for i in range(len(data)): 
     437        for j in range(i + 1, len(data)): 
     438            matrix[i, j] = dist(data[i], data[j]) 
     439             
     440            if progress_callback and count in milestones: 
     441                progress_callback(100.0 * count / msize) 
     442            count += 1 
     443             
     444    return matrix 
  • orange/Orange/evaluation/scoring.py

    r9475 r9483  
    515515    for te in res.results: 
    516516        ress[te.iteration_number].results.append(te) 
    517     return ress     
     517    return ress 
     518 
     519def split_by_classifiers(res): 
     520    """ Splites an instance of :obj:`ExperimentResults` into a list of 
     521    :obj:`ExperimentResults`, one for each classifier.  
     522    """ 
     523    split_res = [] 
     524    for i in range(len(res.classifierNames)): 
     525        r = Orange.evaluation.testing.ExperimentResults(res.numberOfIterations, 
     526                    [res.classifierNames[i]], res.classValues, 
     527                    weights=res.weights, baseClass=res.baseClass, 
     528                    classifiers=[res.classifiers[i]] if res.classifiers else []) 
     529        r.results = [] 
     530        for te in res.results: 
     531            r.results.append(Orange.evaluation.testing.TestedExample(te.iterationNumber, 
     532                                te.actualClass, n=1, weight=te.weight)) 
     533            r.results[-1].classes = [te.classes[i]] 
     534            r.results[-1].probabilities = [te.probabilities[i]] 
     535        split_res.append(r) 
     536    return split_res 
    518537 
    519538 
  • orange/Orange/feature/__init__.py

    r8042 r8506  
    11""" 
    2  
    3 .. index:: feature 
    4  
    5 This module provides functionality for feature scoring, selection,  
    6 discretization, continuzation, imputation, construction and feature 
    7 interaction analysis. 
    8  
    9 ======= 
    10 Scoring 
    11 ======= 
    12  
    13 .. automodule:: Orange.feature.scoring 
    14  
    15 ========= 
    16 Selection 
    17 ========= 
    18  
    19 .. automodule:: Orange.feature.selection 
    20  
    21 ============== 
    22 Discretization 
    23 ============== 
    24  
    25 .. automodule:: Orange.feature.discretization 
    26  
    27 ============== 
    28 Continuization 
    29 ============== 
    30  
    31 .. index:: continuization 
    32  
    33 .. automodule:: Orange.feature.continuization 
    34  
    35 ========== 
    36 Imputation 
    37 ========== 
    38  
    39 .. automodule:: Orange.feature.imputation 
    40  
     2Feature scoring, selection, discretization, continuzation, imputation, 
     3construction and feature interaction analysis. 
    414""" 
    425 
  • orange/Orange/feature/continuization.py

    r8042 r8112  
     1""" 
     2################################### 
     3Continuization (``continuization``) 
     4################################### 
     5""" 
     6 
    17from Orange.core import DomainContinuizer 
  • orange/Orange/feature/discretization.py

    r8042 r8112  
    11""" 
     2################################### 
     3Discretization (``discretization``) 
     4################################### 
    25 
    36.. index:: discretization 
  • orange/Orange/feature/imputation.py

    r8042 r8112  
    11""" 
     2########################### 
     3Imputation (``imputation``) 
     4########################### 
    25 
    36.. index:: imputation 
  • orange/Orange/feature/scoring.py

    r8042 r9483  
    11""" 
     2##################### 
     3Scoring (``scoring``) 
     4##################### 
    25 
    36.. index:: feature scoring 
     
    69   single: feature; feature scoring 
    710 
    8 Feature scoring is used in feature subset selection for classification 
    9 problems. The goal is to find "good" features that are relevant for the given 
    10 classification task. 
    11  
    12 Here is a simple script that reads the data, uses :obj:`attMeasure` to 
    13 derive feature scores and prints out these for the first three best scored 
    14 features. Same scoring function is then used to report (only) on three best 
    15 score features. 
     11Feature scoring is assessment of the usefulness of the feature for  
     12prediction of the dependant (class) variable. 
     13 
     14To compute the information gain of feature "tear_rate" in the Lenses data set (loaded into ``data``) use: 
     15 
     16    >>> meas = Orange.feature.scoring.InfoGain() 
     17    >>> print meas("tear_rate", data) 
     18    0.548794925213 
     19 
     20Apart from information gain you could also use other scoring methods; 
     21see :ref:`classification` and :ref:`regression`. Various 
     22ways to call them are described on :ref:`callingscore`. 
     23 
     24It is possible to construct the object and use 
     25it on-the-fly:: 
     26 
     27    >>> print Orange.feature.scoring.InfoGain("tear_rate", data) 
     28    0.548794925213 
     29 
     30But constructing new instances for each feature is slow for 
     31scoring methods that use caching, such as :obj:`Relief`. 
     32 
     33Scoring features that are not in the domain is also possible. For 
     34instance, discretized features can be scored without producing a 
     35data table in advance (slow with :obj:`Relief`): 
     36 
     37.. literalinclude:: code/scoring-info-iris.py 
     38    :lines: 7-11 
     39 
     40The following example computes feature scores, both with 
     41:obj:`score_all` and by scoring each feature individually, and prints out  
     42the best three features.  
    1643 
    1744.. _scoring-all.py: code/scoring-all.py 
    1845.. _voting.tab: code/voting.tab 
    1946 
    20 `scoring-all.py`_ (uses `voting.tab`_): 
    21  
    2247.. literalinclude:: code/scoring-all.py 
    2348    :lines: 7- 
    2449 
    25 The script should output this:: 
    26  
    27     Feature scores for best three features: 
     50The output:: 
     51 
     52    Feature scores for best three features (with score_all): 
    2853    0.613 physician-fee-freeze 
    29     0.255 adoption-of-the-budget-resolution 
     54    0.255 el-salvador-aid 
    3055    0.228 synfuels-corporation-cutback 
    3156 
    32 .. autoclass:: Orange.feature.scoring.OrderAttributesByMeasure 
    33    :members: 
    34  
    35 .. automethod:: Orange.feature.scoring.MeasureAttribute_Distance 
    36  
    37 .. autoclass:: Orange.feature.scoring.MeasureAttribute_DistanceClass 
    38    :members: 
    39     
    40 .. automethod:: Orange.feature.scoring.MeasureAttribute_MDL 
    41  
    42 .. autoclass:: Orange.feature.scoring.MeasureAttribute_MDLClass 
    43    :members: 
    44  
    45 .. automethod:: Orange.feature.scoring.mergeAttrValues 
    46  
    47 .. automethod:: Orange.feature.scoring.attMeasure 
    48  
    49 ============ 
    50 Base Classes 
    51 ============ 
    52  
    53 There are a number of different measures for assessing the relevance of  
    54 features with respect to much information they contain about the  
    55 corresponding class. These procedures are also known as feature scoring.  
    56 Orange implements several methods that all stem from 
    57 :obj:`Orange.feature.scoring.Measure`. The most of common ones compute 
    58 certain statistics on conditional distributions of class values given 
    59 the feature values; in Orange, these are derived from 
    60 :obj:`Orange.feature.scoring.MeasureAttributeFromProbabilities`. 
    61  
    62 .. class:: Measure 
    63  
    64     This is the base class for a wide range of classes that measure quality of 
    65     features. The class itself is, naturally, abstract. Its fields merely 
    66     describe what kinds of features it can handle and what kind of data it  
    67     requires. 
    68  
    69     .. attribute:: handlesDiscrete 
    70      
    71     Tells whether the measure can handle discrete features. 
    72  
    73     .. attribute:: handlesContinuous 
    74      
    75     Tells whether the measure can handle continuous features. 
    76  
    77     .. attribute:: computesThresholds 
    78      
    79     Tells whether the measure implements the :obj:`thresholdFunction`. 
    80  
    81     .. attribute:: needs 
    82      
    83     Tells what kind of data the measure needs. This can be either 
    84     :obj:`NeedsGenerator`, :obj:`NeedsDomainContingency`, 
    85     :obj:`NeedsContingency_Class`. The first need an instance generator (Relief 
    86     is an example of such measure), the second can compute the quality from 
    87     :obj:`Orange.statistics.contingency.Domain` and the latter only needs the 
    88     contingency (:obj:`Orange.statistics.contingency.VarClass`) the feature 
    89     distribution and the apriori class distribution. Most measures only need the 
    90     latter. 
    91  
    92     Several (but not all) measures can treat unknown feature values in 
    93     different ways, depending on field :obj:`unknownsTreatment` (this field is 
    94     not defined in :obj:`Measure` but in many derived classes). Undefined  
    95     values can be: 
    96      
    97     * ignored (:obj:`Measure.IgnoreUnknowns`); this has the same effect as if  
    98       the example for which the feature value is unknown are removed. 
    99  
    100     * punished (:obj:`Measure.ReduceByUnknown`); the feature quality is 
    101       reduced by the proportion of unknown values. In impurity measures, this 
    102       can be interpreted as if the impurity is decreased only on examples for 
    103       which the value is defined and stays the same for the others, and the 
    104       feature quality is the average impurity decrease. 
    105        
    106     * imputed (:obj:`Measure.UnknownsToCommon`); here, undefined values are 
    107       replaced by the most common feature value. If you want a more clever 
    108       imputation, you should do it in advance. 
    109  
    110     * treated as a separate value (:obj:`MeasureAttribute.UnknownsAsValue`) 
    111  
    112     The default treatment is :obj:`ReduceByUnknown`, which is optimal in most 
    113     cases and does not make additional presumptions (as, for instance, 
    114     :obj:`UnknownsToCommon` which supposes that missing values are not for 
    115     instance, results of measurements that were not performed due to 
    116     information extracted from the other features). Use other treatments if 
    117     you know that they make better sense on your data. 
    118  
    119     The only method supported by all measures is the call operator to which we 
    120     pass the data and get the number representing the quality of the feature. 
    121     The number does not have any absolute meaning and can vary widely for 
    122     different feature measures. The only common characteristic is that 
    123     higher the value, better the feature. If the feature is so bad that  
    124     it's quality cannot be measured, the measure returns 
    125     :obj:`Measure.Rejected`. None of the measures described here do so. 
    126  
    127     There are different sets of arguments that the call operator can accept. 
    128     Not all classes will accept all kinds of arguments. Relief, for instance, 
    129     cannot be computed from contingencies alone. Besides, the feature and 
    130     the class need to be of the correct type for a particular measure. 
    131  
    132     There are three call operators just to make your life simpler and faster. 
    133     When working with the data, your method might have already computed, for 
    134     instance, contingency matrix. If so and if the quality measure you use is 
    135     OK with that (as most measures are), you can pass the contingency matrix 
    136     and the measure will compute much faster. If, on the other hand, you only 
    137     have examples and haven't computed any statistics on them, you can pass 
    138     examples (and, optionally, an id for meta-feature with weights) and the 
    139     measure will compute the contingency itself, if needed. 
    140  
    141     .. method:: __call__(attribute, examples[, apriori class distribution][, weightID]) 
    142     .. method:: __call__(attribute, domain contingency[, apriori class distribution]) 
    143     .. method:: __call__(contingency, class distribution[, apriori class distribution]) 
    144  
    145         :param attribute: gives the feature whose quality is to be assessed. 
    146           This can be either a descriptor, an index into domain or a name. In 
    147           the first form, if the feature is given by descriptor, it doesn't 
    148           need to be in the domain. It needs to be computable from the 
    149           feature in the domain, though. 
    150            
    151         Data is given either as examples (and, optionally, id for meta-feature 
    152         with weight), contingency tables 
    153         (:obj:`Orange.statistics.contingency.Domain`) or distributions 
    154         (:obj:`Orange.statistics.distribution.Distribution`) for all 
    155         attributes. In the latter for, what is given as the class distribution 
    156         depends upon what you do with unknown values (if there are any).  If 
    157         :obj:`unknownsTreatment` is :obj:`IgnoreUnknowns`, the class 
    158         distribution should be computed on examples for which the feature value 
    159         is defined. Otherwise, class distribution should be the overall class 
    160         distribution. 
    161  
    162         The optional argument with apriori class distribution is 
    163         most often ignored. It comes handy if the measure makes any probability 
    164         estimates based on apriori class probabilities (such as m-estimate). 
    165  
    166     .. method:: thresholdFunction(attribute, examples[, weightID]) 
    167      
    168     This function computes the qualities for different binarizations of the 
    169     continuous feature :obj:`attribute`. The feature should of course be 
    170     continuous. The result of a function is a list of tuples, where the first 
    171     element represents a threshold (all splits in the middle between two 
    172     existing feature values), the second is the measured quality for a 
    173     corresponding binary feature and the last one is the distribution which 
    174     gives the number of examples below and above the threshold. The last 
    175     element, though, may be missing; generally, if the particular measure can 
    176     get the distribution without any computational burden, it will do so and 
    177     the caller can use it. If not, the caller needs to compute it itself. 
    178  
    179     The script below shows different ways to assess the quality of astigmatic, 
    180     tear rate and the first feature (whichever it is) in the dataset lenses. 
    181  
    182     .. literalinclude:: code/scoring-info-lenses.py 
    183         :lines: 7-21 
    184  
    185     As for many other classes in Orange, you can construct the object and use 
    186     it on-the-fly. For instance, to measure the quality of feature 
    187     "tear_rate", you could write simply:: 
    188  
    189         >>> print Orange.feature.scoring.Info("tear_rate", data) 
    190         0.548794984818 
    191  
    192     You shouldn't use this shortcut with ReliefF, though; see the explanation 
    193     in the section on ReliefF. 
    194  
    195     It is also possible to assess the quality of features that do not exist 
    196     in the features. For instance, you can assess the quality of discretized 
    197     features without constructing a new domain and dataset that would include 
    198     them. 
    199  
    200     `scoring-info-iris.py`_ (uses `iris.tab`_): 
    201  
    202     .. literalinclude:: code/scoring-info-iris.py 
    203         :lines: 7-11 
    204  
    205     The quality of the new feature d1 is assessed on data, which does not 
    206     include the new feature at all. (Note that ReliefF won't do that since 
    207     it would be too slow. ReliefF requires the feature to be present in the 
    208     dataset.) 
    209  
    210     Finally, you can compute the quality of meta-features. The following 
    211     script adds a meta-feature to an example table, initializes it to random 
    212     values and measures its information gain. 
    213  
    214     `scoring-info-lenses.py`_ (uses `lenses.tab`_): 
    215  
    216     .. literalinclude:: code/scoring-info-lenses.py 
    217         :lines: 54- 
    218  
    219     To show the computation of thresholds, we shall use the Iris data set. 
    220  
    221     `scoring-info-iris.py`_ (uses `iris.tab`_): 
    222  
    223     .. literalinclude:: code/scoring-info-iris.py 
    224         :lines: 7-15 
    225  
    226     If we hadn't constructed the feature in advance, we could write  
    227     `Orange.feature.scoring.Relief().thresholdFunction("petal length", data)`. 
    228     This is not recommendable for ReliefF, since it may be a lot slower. 
    229  
    230     The script below finds and prints out the best threshold for binarization 
    231     of an feature, that is, the threshold with which the resulting binary 
    232     feature will have the optimal ReliefF (or any other measure):: 
    233  
    234         thresh, score, distr = meas.bestThreshold("petal length", data) 
    235         print "Best threshold: %5.3f (score %5.3f)" % (thresh, score) 
    236  
    237 .. class:: MeasureAttributeFromProbabilities 
    238  
    239     This is the abstract base class for feature quality measures that can be 
    240     computed from contingency matrices only. It relieves the derived classes 
    241     from having to compute the contingency matrix by defining the first two 
    242     forms of call operator. (Well, that's not something you need to know if 
    243     you only work in Python.) Additional feature of this class is that you can 
    244     set probability estimators. If none are given, probabilities and 
    245     conditional probabilities of classes are estimated by relative frequencies. 
    246  
    247     .. attribute:: unknownsTreatment 
    248       
    249     Defines what to do with unknown values. See the possibilities described above. 
    250  
    251     .. attribute:: estimatorConstructor 
    252     .. attribute:: conditionalEstimatorConstructor 
    253      
    254     The classes that are used to estimate unconditional and conditional 
    255     probabilities of classes, respectively. You can set this to, for instance,  
    256     :obj:`ProbabilityEstimatorConstructor_m` and  
    257     :obj:`ConditionalProbabilityEstimatorConstructor_ByRows` 
    258     (with estimator constructor again set to  
    259     :obj:`ProbabilityEstimatorConstructor_m`), respectively. 
     57    Feature scores for best three features (scored individually): 
     58    0.613 physician-fee-freeze 
     59    0.255 el-salvador-aid 
     60    0.228 synfuels-corporation-cutback 
     61 
     62.. comment:: 
     63 
     64    The next script uses :obj:`GainRatio` and :obj:`Relief`. 
     65 
     66    .. literalinclude:: code/scoring-relief-gainRatio.py 
     67        :lines: 7- 
     68 
     69    Notice that on this data the ranks of features match:: 
     70         
     71        Relief GainRt Feature 
     72        0.613  0.752  physician-fee-freeze 
     73        0.255  0.444  el-salvador-aid 
     74        0.228  0.414  synfuels-corporation-cutback 
     75        0.189  0.382  crime 
     76        0.166  0.345  adoption-of-the-budget-resolution 
     77 
     78 
     79.. _callingscore: 
     80 
     81======================= 
     82Calling scoring methods 
     83======================= 
     84 
     85To score a feature use :obj:`Score.__call__`. There are diferent 
     86function signatures, which enable optimization. For instance, 
     87if contingency matrix has already been computed, you can speed 
     88up the computation by passing it to the scoring method (if it supports 
     89that form - most do). Otherwise the scoring method will have to compute the 
     90contingency itself. 
     91 
     92Not all classes accept all kinds of arguments. :obj:`Relief`, 
     93for instance, only supports the form with instances on the input. 
     94 
     95.. method:: Score.__call__(attribute, instances[, apriori_class_distribution][, weightID]) 
     96 
     97    :param attribute: the chosen feature, either as a descriptor,  
     98      index, or a name. 
     99    :type attribute: :class:`Orange.data.variable.Variable` or int or string 
     100    :param instances: data. 
     101    :type instances: `Orange.data.Table` 
     102    :param weightID: id for meta-feature with weight. 
     103 
     104    All scoring methods need to support these parameters. 
     105 
     106.. method:: Score.__call__(attribute, domain_contingency[, apriori_class_distribution]) 
     107 
     108    :param attribute: the chosen feature, either as a descriptor,  
     109      index, or a name. 
     110    :type attribute: :class:`Orange.data.variable.Variable` or int or string 
     111    :param domain_contingency:  
     112    :type domain_contingency: :obj:`Orange.statistics.contingency.Domain` 
     113 
     114.. method:: Score.__call__(contingency, class_distribution[, apriori_class_distribution]) 
     115 
     116    :param contingency: 
     117    :type contingency: :obj:`Orange.statistics.contingency.VarClass` 
     118    :param class_distribution: distribution of the class 
     119      variable. If :obj:`unknowns_treatment` is :obj:`IgnoreUnknowns`, 
     120      it should be computed on instances where feature value is 
     121      defined. Otherwise, class distribution should be the overall 
     122      class distribution. 
     123    :type class_distribution:  
     124      :obj:`Orange.statistics.distribution.Distribution` 
     125    :param apriori_class_distribution: Optional and most often 
     126      ignored. Useful if the scoring method makes any probability estimates 
     127      based on apriori class probabilities (such as the m-estimate). 
     128    :return: Feature score - the higher the value, the better the feature. 
     129      If the quality cannot be scored, return :obj:`Score.Rejected`. 
     130    :rtype: float or :obj:`Score.Rejected`. 
     131 
     132The code below scores the same feature with :obj:`GainRatio` in 
     133different ways. 
     134 
     135.. literalinclude:: code/scoring-calls.py 
     136    :lines: 7- 
     137 
     138.. _classification: 
    260139 
    261140=========================== 
    262 Measures for Classification 
     141Feature scoring in classification problems 
    263142=========================== 
    264143 
    265 This script scores features with gain ratio and relief. 
    266  
    267 `scoring-relief-gainRatio.py`_ (uses `voting.tab`_): 
    268  
    269 .. literalinclude:: code/scoring-relief-gainRatio.py 
    270     :lines: 7- 
    271  
    272 Notice that on this data the ranks of features match rather well:: 
    273      
    274     Relief GainRt Feature 
    275     0.613  0.752  physician-fee-freeze 
    276     0.255  0.444  el-salvador-aid 
    277     0.228  0.414  synfuels-corporation-cutback 
    278     0.189  0.382  crime 
    279     0.166  0.345  adoption-of-the-budget-resolution 
    280  
    281 The following section describes the feature quality measures suitable for  
    282 discrete features and outcomes.  
    283 See  `scoring-info-lenses.py`_, `scoring-info-iris.py`_, 
    284 `scoring-diff-measures.py`_ and `scoring-regression.py`_ 
    285 for more examples on their use. 
     144.. Undocumented: MeasureAttribute_IM, MeasureAttribute_chiSquare, MeasureAttribute_gainRatioA, MeasureAttribute_logOddsRatio, MeasureAttribute_splitGain. 
    286145 
    287146.. index::  
     
    290149.. class:: InfoGain 
    291150 
    292     The most popular measure, information gain :obj:`Info` measures the expected 
    293     decrease of the entropy. 
     151    Information gain - the expected decrease of entropy. See `page on wikipedia 
     152    <http://en.wikipedia.org/wiki/Information_gain_ratio>`_. 
    294153 
    295154.. index::  
     
    298157.. class:: GainRatio 
    299158 
    300     Gain ratio :obj:`GainRatio` was introduced by Quinlan in order to avoid 
    301     overestimation of multi-valued features. It is computed as information 
    302     gain divided by the entropy of the feature's value. (It has been shown, 
    303     however, that such measure still overstimates the features with multiple 
    304     values.) 
     159    Information gain ratio - information gain divided by the entropy of the feature's 
     160    value. Introduced in [Quinlan1986]_ in order to avoid overestimation 
     161    of multi-valued features. It has been shown, however, that it still 
     162    overestimates features with multiple values. See `Wikipedia 
     163    <http://en.wikipedia.org/wiki/Information_gain_ratio>`_. 
    305164 
    306165.. index::  
     
    309168.. class:: Gini 
    310169 
    311     Gini index :obj:`Gini` was first introduced by Breiman and can be interpreted 
    312     as the probability that two randomly chosen examples will have different 
    313     classes. 
     170    Gini index is the probability that two randomly chosen instances will have different 
     171    classes. See `Gini coefficient on Wikipedia <http://en.wikipedia.org/wiki/Gini_coefficient>`_. 
    314172 
    315173.. index::  
     
    318176.. class:: Relevance 
    319177 
    320     Relevance of features :obj:`Relevance` is a measure that discriminate 
    321     between features on the basis of their potential value in the formation of 
    322     decision rules. 
     178    The potential value for decision rules. 
    323179 
    324180.. index::  
     
    327183.. class:: Cost 
    328184 
    329     Evaluates features based on the "saving" achieved by knowing the value of 
     185    Evaluates features based on the cost decrease achieved by knowing the value of 
    330186    feature, according to the specified cost matrix. 
    331187 
    332188    .. attribute:: cost 
    333189      
    334     Cost matrix, see :obj:`Orange.classification.CostMatrix` for details. 
    335  
    336     If cost of predicting the first class for an example that is actually in 
     190        Cost matrix, see :obj:`Orange.classification.CostMatrix` for details. 
     191 
     192    If the cost of predicting the first class of an instance that is actually in 
    337193    the second is 5, and the cost of the opposite error is 1, than an appropriate 
    338     measure can be constructed and used for feature 3 as follows:: 
     194    score can be constructed as follows:: 
     195 
    339196 
    340197        >>> meas = Orange.feature.scoring.Cost() 
     
    343200        0.083333350718021393 
    344201 
    345     This tells that knowing the value of feature 3 would decrease the 
    346     classification cost for appx 0.083 per example. 
     202    Knowing the value of feature 3 would decrease the 
     203    classification cost for approximately 0.083 per instance. 
     204 
     205    .. comment:: opposite error - is this term correct? TODO 
    347206 
    348207.. index::  
     
    351210.. class:: Relief 
    352211 
    353     ReliefF :obj:`Relief` was first developed by Kira and Rendell and then 
    354     substantially generalized and improved by Kononenko. It measures the 
    355     usefulness of features based on their ability to distinguish between 
    356     very similar examples belonging to different classes. 
     212    Assesses features' ability to distinguish between very similar 
     213    instances from different classes. This scoring method was 
     214    first developed by Kira and 
     215    Rendell and then improved by Kononenko. The class :obj:`Relief` 
     216    works on discrete and continuous classes and thus implements ReliefF 
     217    and RReliefF. 
    357218 
    358219    .. attribute:: k 
    359220     
    360     Number of neighbours for each example. Default is 5. 
     221       Number of neighbours for each instance. Default is 5. 
    361222 
    362223    .. attribute:: m 
    363224     
    364     Number of reference examples. Default is 100. Set to -1 to take all the 
    365     examples. 
    366  
    367     .. attribute:: checkCachedData 
    368      
    369     A flag best left alone unless you know what you do. 
    370  
    371 Computation of ReliefF is rather slow since it needs to find k nearest 
    372 neighbours for each of m reference examples (or all examples, if m is set to 
    373 -1). Since we normally compute ReliefF for all features in the dataset, 
    374 :obj:`Relief` caches the results. When it is called to compute a quality of 
    375 certain feature, it computes qualities for all features in the dataset. 
    376 When called again, it uses the stored results if the data has not changeddomain 
    377 is still the same and the example table has not changed. Checking is done by 
    378 comparing the data table version :obj:`Orange.data.Table` for details) and then 
    379 computing a checksum of the data and comparing it with the previous checksum. 
    380 The latter can take some time on large tables, so you may want to disable it 
    381 by setting `checkCachedData` to :obj:`False`. In most cases it will do no harm, 
    382 except when the data is changed in such a way that it passed unnoticed by the  
    383 version' control, in which cases the computed ReliefFs can be false. Hence: 
    384 disable it if you know that the data does not change or if you know what kind 
    385 of changes are detected by the version control. 
    386  
    387 Caching will only have an effect if you use the same instance for all 
    388 features in the domain. So, don't do this:: 
    389  
    390     for attr in data.domain.attributes: 
    391         print Orange.feature.scoring.Relief(attr, data) 
    392  
    393 In this script, cached data dies together with the instance of :obj:`Relief`, 
    394 which is constructed and destructed for each feature separately. It's way 
    395 faster to go like this:: 
    396  
    397     meas = Orange.feature.scoring.Relief() 
    398     for attr in table.domain.attributes: 
    399         print meas(attr, data) 
    400  
    401 When called for the first time, meas will compute ReliefF for all features 
    402 and the subsequent calls simply return the stored data. 
    403  
    404 Class :obj:`Relief` works on discrete and continuous classes and thus  
    405 implements functionality of algorithms ReliefF and RReliefF. 
    406  
    407 .. note:: 
    408    ReliefF can also compute the threshold function, that is, the feature 
    409    quality at different thresholds for binarization. 
    410  
    411 Finally, here is an example which shows what can happen if you disable the  
    412 computation of checksums:: 
    413  
    414     table = Orange.data.Table("iris") 
    415     r1 = Orange.feature.scoring.Relief() 
    416     r2 = Orange.feature.scoring.Relief(checkCachedData = False) 
    417  
    418     print "%.3f\\t%.3f" % (r1(0, table), r2(0, table)) 
    419     for ex in table: 
    420         ex[0] = 0 
    421     print "%.3f\\t%.3f" % (r1(0, table), r2(0, table)) 
    422  
    423 The first print prints out the same number, 0.321 twice. Then we annulate the 
    424 first feature. r1 notices it and returns -1 as it's ReliefF, 
    425 while r2 does not and returns the same number, 0.321, which is now wrong. 
     225        Number of reference instances. Default is 100. Set to -1 to take all the 
     226        instances. 
     227 
     228    .. attribute:: check_cached_data 
     229     
     230        Check if the cached data is changed with data checksum. Slow 
     231        on large tables.  Defaults to :obj:`True`. Disable it if you know that 
     232        the data will not change. 
     233 
     234    ReliefF is slow since it needs to find k nearest neighbours for 
     235    each of m reference instances. As we normally compute ReliefF for 
     236    all features in the dataset, :obj:`Relief` caches the results for 
     237    all features, when called to score a certain feature.  When called 
     238    again, it uses the stored results if the domain and the data table 
     239    have not changed (data table version and the data checksum are 
     240    compared). Caching will only work if you use the same object.  
     241    Constructing new instances of :obj:`Relief` fir each feature, 
     242    like this:: 
     243 
     244        for attr in data.domain.attributes: 
     245            print Orange.feature.scoring.Relief(attr, data) 
     246 
     247    runs much slower than reusing the same instance:: 
     248 
     249        meas = Orange.feature.scoring.Relief() 
     250        for attr in table.domain.attributes: 
     251            print meas(attr, data) 
     252 
     253    .. note:: 
     254       Relief can also compute the threshold function, that is, the feature 
     255       quality at different thresholds for binarization. 
     256 
     257.. autoclass:: Orange.feature.scoring.Distance 
     258    
     259.. autoclass:: Orange.feature.scoring.MDL 
     260 
     261.. _regression: 
    426262 
    427263======================= 
    428 Measures for Regression 
     264Feature scoring in regression problems 
    429265======================= 
    430266 
    431 Except for ReliefF, the only feature quality measure available for regression 
    432 problems is based on a mean square error. 
     267You can also use :obj:`Relief` for regression. 
    433268 
    434269.. index::  
     
    437272.. class:: MSE 
    438273 
    439     Implements the mean square error measure. 
    440  
    441     .. attribute:: unknownsTreatment 
    442      
    443     Tells what to do with unknown feature values. See description on the top 
    444     of this page. 
     274    Implements the mean square error score. 
     275 
     276    .. attribute:: unknowns_treatment 
     277     
     278        What to do with unknown values. See :obj:`Score.unknowns_treatment`. 
    445279 
    446280    .. attribute:: m 
    447281     
    448     Parameter for m-estimate of error. Default is 0 (no m-estimate). 
    449  
    450 ========== 
    451 References 
    452 ========== 
    453  
    454 * Igor Kononeko, Matjaz Kukar: Machine Learning and Data Mining,  
     282        Parameter for m-estimate of error. Default is 0 (no m-estimate). 
     283 
     284 
     285 
     286============ 
     287Base Classes 
     288============ 
     289 
     290Implemented methods for scoring relevances of features to the class 
     291are subclasses of :obj:`Score`. Those that compute statistics on 
     292conditional distributions of class values given the feature values are 
     293derived from :obj:`ScoreFromProbabilities`. 
     294 
     295.. class:: Score 
     296 
     297    Abstract base class for feature scoring. Its attributes describe which 
     298    features it can handle and the required data. 
     299 
     300    **Capabilities** 
     301 
     302    .. attribute:: handles_discrete 
     303     
     304        Indicates whether the scoring method can handle discrete features. 
     305 
     306    .. attribute:: handles_continuous 
     307     
     308        Indicates whether the scoring method can handle continuous features. 
     309 
     310    .. attribute:: computes_thresholds 
     311     
     312        Indicates whether the scoring method implements the :obj:`threshold_function`. 
     313 
     314    **Input specification** 
     315 
     316    .. attribute:: needs 
     317     
     318        The type of data needed: :obj:`Generator`, :obj:`DomainContingency`, 
     319        or :obj:`Contingency_Class`. 
     320 
     321    .. attribute:: Generator 
     322 
     323        Constant. Indicates that the scoring method needs an instance generator on the input (as, for example, 
     324        :obj:`Relief`). 
     325 
     326    .. attribute:: DomainContingency 
     327 
     328        Constant. Indicates that the scoring method needs :obj:`Orange.statistics.contingency.Domain`. 
     329 
     330    .. attribute:: Contingency_Class 
     331 
     332        Constant. Indicates, that the scoring method needs the contingency 
     333        (:obj:`Orange.statistics.contingency.VarClass`), feature 
     334        distribution and the apriori class distribution (as most 
     335        scoring methods). 
     336 
     337    **Treatment of unknown values** 
     338 
     339    .. attribute:: unknowns_treatment 
     340 
     341        Not defined in :obj:`Score` but defined in 
     342        classes that are able to treat unknown values. Either 
     343        :obj:`IgnoreUnknowns`, :obj:`ReduceByUnknown`. 
     344        :obj:`UnknownsToCommon`, or :obj:`UnknownsAsValue`. 
     345 
     346    .. attribute:: IgnoreUnknowns 
     347 
     348        Constant. Instances for which the feature value is unknown are removed. 
     349 
     350    .. attribute:: ReduceByUnknown 
     351 
     352        Constant. Features with unknown values are  
     353        punished. The feature quality is reduced by the proportion of 
     354        unknown values. For impurity scores the impurity decreases 
     355        only where the value is defined and stays the same otherwise. 
     356 
     357    .. attribute:: UnknownsToCommon 
     358 
     359        Constant. Undefined values are replaced by the most common value. 
     360 
     361    .. attribute:: UnknownsAsValue 
     362 
     363        Constant. Unknown values are treated as a separate value. 
     364 
     365    **Methods** 
     366 
     367    .. method:: __call__ 
     368 
     369        Abstract. See :ref:`callingscore`. 
     370 
     371    .. method:: threshold_function(attribute, instances[, weightID]) 
     372     
     373        Abstract.  
     374         
     375        Assess different binarizations of the continuous feature 
     376        :obj:`attribute`.  Return a list of tuples, where the first 
     377        element is a threshold (between two existing values), the second 
     378        is the quality of the corresponding binary feature, and the last 
     379        the distribution of instancs below and above the threshold. The 
     380        last element is optional. 
     381 
     382        To show the computation of thresholds, we shall use the Iris data set 
     383        (part of `scoring-info-iris.py`_, uses `iris.tab`_): 
     384 
     385        .. literalinclude:: code/scoring-info-iris.py 
     386            :lines: 13-15 
     387 
     388    .. method:: best_threshold(attribute, instances) 
     389 
     390        Return the best threshold for binarization, that is, the threshold 
     391        with which the resulting binary feature will have the optimal 
     392        score. 
     393 
     394        The script below prints out the best threshold for 
     395        binarization of an feature. ReliefF is used scoring: (part of 
     396        `scoring-info-iris.py`_, uses `iris.tab`_): 
     397 
     398        .. literalinclude:: code/scoring-info-iris.py 
     399            :lines: 17-18 
     400 
     401.. class:: ScoreFromProbabilities 
     402 
     403    Bases: :obj:`Score` 
     404 
     405    Abstract base class for feature scoring method that can be 
     406    computed from contingency matrices only. It relieves the derived classes 
     407    from having to compute the contingency matrix by defining the first two 
     408    forms of call operator. (Well, that's not something you need to know if 
     409    you only work in Python.) 
     410 
     411    .. attribute:: unknowns_treatment 
     412      
     413        See :obj:`Score.unknowns_treatment`. 
     414 
     415    .. attribute:: estimator_constructor 
     416    .. attribute:: conditional_estimator_constructor 
     417     
     418        The classes that are used to estimate unconditional and 
     419        conditional probabilities of classes, respectively. You can set 
     420        this to, for instance, :obj:`ProbabilityEstimatorConstructor_m` 
     421        and :obj:`ConditionalProbabilityEstimatorConstructor_ByRows` 
     422        (with estimator constructor again set to 
     423        :obj:`ProbabilityEstimatorConstructor_m`), respectively. 
     424        Both default to relative frequencies. 
     425 
     426============ 
     427Other 
     428============ 
     429 
     430.. autoclass:: Orange.feature.scoring.OrderAttributes 
     431   :members: 
     432 
     433.. autofunction:: Orange.feature.scoring.merge_values 
     434 
     435.. autofunction:: Orange.feature.scoring.score_all 
     436 
     437.. comment .. rubric:: References 
     438 
     439.. [Kononenko2007] Igor Kononenko, Matjaz Kukar: Machine Learning and Data Mining,  
    455440  Woodhead Publishing, 2007. 
     441 
     442.. [Quinlan1986] J R Quinlan: Induction of Decision Trees, Machine Learning, 1986. 
     443 
     444.. [Breiman1984] L Breiman et al: Classification and Regression Trees, Chapman and Hall, 1984. 
     445 
     446.. [Kononenko1995] I Kononenko: On biases in estimating multi-valued attributes, International Joint Conference on Artificial Intelligence, 1995. 
    456447 
    457448.. _iris.tab: code/iris.tab 
     
    470461 
    471462import Orange.core as orange 
    472  
    473 from orange import MeasureAttribute as Measure 
     463import Orange.misc 
     464 
     465from orange import MeasureAttribute as Score 
     466from orange import MeasureAttributeFromProbabilities as ScoreFromProbabilities 
    474467from orange import MeasureAttribute_info as InfoGain 
    475468from orange import MeasureAttribute_gainRatio as GainRatio 
     
    480473from orange import MeasureAttribute_MSE as MSE 
    481474 
     475 
    482476###### 
    483477# from orngEvalAttr.py 
    484 class OrderAttributesByMeasure: 
    485     """Construct an instance that orders features by their scores. 
    486      
    487     :param measure: a feature measure, derived from  
    488       :obj:`Orange.feature.scoring.Measure`. 
     478 
     479class OrderAttributes: 
     480    """Orders features by their scores. 
     481     
     482    .. attribute::  score 
     483     
     484        A scoring method derived from :obj:`~Orange.feature.scoring.Score`. 
     485        If :obj:`None`, :obj:`Relief` with m=5 and k=10 will be used. 
    489486     
    490487    """ 
    491     def __init__(self, measure=None): 
    492         self.measure = measure 
     488    def __init__(self, score=None): 
     489        self.score = score 
    493490 
    494491    def __call__(self, data, weight): 
    495         """Take :obj:`Orange.data.table` data table and an instance of 
    496         :obj:`Orange.feature.scoring.Measure` to score and order features.   
     492        """Score and order all features. 
    497493 
    498494        :param data: a data table used to score features 
    499         :type data: Orange.data.table 
    500  
    501         :param weight: meta feature that stores weights of individual data 
    502           instances 
    503         :type weight: Orange.data.variable 
     495        :type data: Orange.data.Table 
     496 
     497        :param weight: meta attribute that stores weights of instances 
     498        :type weight: Orange.data.variable.Variable 
    504499 
    505500        """ 
    506         if self.measure: 
    507             measure = self.measure 
     501        if self.score: 
     502            measure = self.score 
    508503        else: 
    509             measure = Relief(m=5,k=10) 
     504            measure = Relief(m=5, k=10) 
    510505 
    511506        measured = [(attr, measure(attr, data, None, weight)) for attr in data.domain.attributes] 
     
    513508        return [x[0] for x in measured] 
    514509 
    515 def MeasureAttribute_Distance(attr = None, data = None): 
    516     """Instantiate :obj:`MeasureAttribute_DistanceClass` and use it to return 
    517     the score of a given feature on given data. 
    518      
    519     :param attr: feature to score 
    520     :type attr: Orange.data.variable 
    521      
    522     :param data: data table used for feature scoring 
    523     :type data: Orange.data.table  
    524      
     510OrderAttributes = Orange.misc.deprecated_members({ 
     511          "measure": "score", 
     512}, wrap_methods=[])(OrderAttributes) 
     513 
     514class Distance(Score): 
     515    """The :math:`1-D` distance is defined as information gain divided 
     516    by joint entropy :math:`H_{CA}` (:math:`C` is the class variable 
     517    and :math:`A` the feature): 
     518 
     519    .. math:: 
     520        1-D(C,A) = \\frac{\\mathrm{Gain}(A)}{H_{CA}} 
    525521    """ 
    526     m = MeasureAttribute_DistanceClass() 
    527     if attr != None and data != None: 
    528         return m(attr, data) 
    529     else: 
    530         return m 
    531  
    532 class MeasureAttribute_DistanceClass(orange.MeasureAttribute): 
    533     """Implement the 1-D feature distance measure described in Kononenko.""" 
    534     def __call__(self, attr, data, aprioriDist = None, weightID = None): 
    535         """Take :obj:`Orange.data.table` data table and score the given  
    536         :obj:`Orange.data.variable`. 
     522 
     523    @Orange.misc.deprecated_keywords({"aprioriDist": "apriori_dist"}) 
     524    def __new__(cls, attr=None, data=None, apriori_dist=None, weightID=None): 
     525        self = Score.__new__(cls) 
     526        if attr != None and data != None: 
     527            #self.__init__(**argkw) 
     528            return self.__call__(attr, data, apriori_dist, weightID) 
     529        else: 
     530            return self 
     531 
     532    @Orange.misc.deprecated_keywords({"aprioriDist": "apriori_dist"}) 
     533    def __call__(self, attr, data, apriori_dist=None, weightID=None): 
     534        """Score the given feature. 
    537535 
    538536        :param attr: feature to score 
    539         :type attr: Orange.data.variable 
     537        :type attr: Orange.data.variable.Variable 
    540538 
    541539        :param data: a data table used to score features 
    542540        :type data: Orange.data.table 
    543541 
    544         :param aprioriDist:  
    545         :type aprioriDist: 
     542        :param apriori_dist:  
     543        :type apriori_dist: 
    546544         
    547545        :param weightID: meta feature used to weight individual data instances 
    548         :type weightID: Orange.data.variable 
     546        :type weightID: Orange.data.variable.Variable 
    549547 
    550548        """ 
     
    564562            return 0 
    565563 
    566 def MeasureAttribute_MDL(attr = None, data = None): 
    567     """Instantiate :obj:`MeasureAttribute_MDLClass` and use it n given data to 
    568     return the feature's score.""" 
    569     m = MeasureAttribute_MDLClass() 
    570     if attr != None and data != None: 
    571         return m(attr, data) 
    572     else: 
    573         return m 
    574  
    575 class MeasureAttribute_MDLClass(orange.MeasureAttribute): 
    576     """Score feature based on the minimum description length principle.""" 
    577     def __call__(self, attr, data, aprioriDist = None, weightID = None): 
    578         """Take :obj:`Orange.data.table` data table and score the given  
    579         :obj:`Orange.data.variable`. 
     564class MDL(Score): 
     565    """Minimum description length principle [Kononenko1995]_. Let 
     566    :math:`n` be the number of instances, :math:`n_0` the number of 
     567    classes, and :math:`n_{cj}` the number of instances with feature 
     568    value :math:`j` and class value :math:`c`. Then MDL score for the 
     569    feature A is 
     570 
     571    .. math:: 
     572         \mathrm{MDL}(A) = \\frac{1}{n} \\Bigg[ 
     573         \\log\\binom{n}{n_{1.},\\cdots,n_{n_0 .}} - \\sum_j 
     574         \\log \\binom{n_{.j}}{n_{1j},\\cdots,n_{n_0 j}} \\\\ 
     575         + \\log \\binom{n+n_0-1}{n_0-1} - \\sum_j \\log 
     576         \\binom{n_{.j}+n_0-1}{n_0-1} 
     577         \\Bigg] 
     578    """ 
     579 
     580    @Orange.misc.deprecated_keywords({"aprioriDist": "apriori_dist"}) 
     581    def __new__(cls, attr=None, data=None, apriori_dist=None, weightID=None): 
     582        self = Score.__new__(cls) 
     583        if attr != None and data != None: 
     584            #self.__init__(**argkw) 
     585            return self.__call__(attr, data, apriori_dist, weightID) 
     586        else: 
     587            return self 
     588 
     589    @Orange.misc.deprecated_keywords({"aprioriDist": "apriori_dist"}) 
     590    def __call__(self, attr, data, apriori_dist=None, weightID=None): 
     591        """Score the given feature. 
    580592 
    581593        :param attr: feature to score 
    582         :type attr: Orange.data.variable 
     594        :type attr: Orange.data.variable.Variable 
    583595 
    584596        :param data: a data table used to score the feature 
    585597        :type data: Orange.data.table 
    586598 
    587         :param aprioriDist:  
    588         :type aprioriDist: 
     599        :param apriori_dist:  
     600        :type apriori_dist: 
    589601         
    590602        :param weightID: meta feature used to weight individual data instances 
    591         :type weightID: Orange.data.variable 
     603        :type weightID: Orange.data.variable.Variable 
    592604 
    593605        """ 
     
    626638    return ret 
    627639 
    628 def mergeAttrValues(data, attrList, attrMeasure, removeUnusedValues = 1): 
     640 
     641@Orange.misc.deprecated_keywords({"attrList": "attr_list", "attrMeasure": "attr_score", "removeUnusedValues": "remove_unused_values"}) 
     642def merge_values(data, attr_list, attr_score, remove_unused_values = 1): 
    629643    import orngCI 
    630     #data = data.select([data.domain[attr] for attr in attrList] + [data.domain.classVar]) 
    631     newData = data.select(attrList + [data.domain.classVar]) 
    632     newAttr = orngCI.FeatureByCartesianProduct(newData, attrList)[0] 
     644    #data = data.select([data.domain[attr] for attr in attr_list] + [data.domain.classVar]) 
     645    newData = data.select(attr_list + [data.domain.class_var]) 
     646    newAttr = orngCI.FeatureByCartesianProduct(newData, attr_list)[0] 
    633647    dist = orange.Distribution(newAttr, newData) 
    634648    activeValues = [] 
    635649    for i in range(len(newAttr.values)): 
    636650        if dist[newAttr.values[i]] > 0: activeValues.append(i) 
    637     currScore = attrMeasure(newAttr, newData) 
     651    currScore = attr_score(newAttr, newData) 
    638652    while 1: 
    639653        bestScore, bestMerge = currScore, None 
    640654        for i1, ind1 in enumerate(activeValues): 
    641             oldInd1 = newAttr.getValueFrom.lookupTable[ind1] 
     655            oldInd1 = newAttr.get_value_from.lookupTable[ind1] 
    642656            for ind2 in activeValues[:i1]: 
    643                 newAttr.getValueFrom.lookupTable[ind1] = ind2 
    644                 score = attrMeasure(newAttr, newData) 
     657                newAttr.get_value_from.lookupTable[ind1] = ind2 
     658                score = attr_score(newAttr, newData) 
    645659                if score >= bestScore: 
    646660                    bestScore, bestMerge = score, (ind1, ind2) 
    647                 newAttr.getValueFrom.lookupTable[ind1] = oldInd1 
     661                newAttr.get_value_from.lookupTable[ind1] = oldInd1 
    648662 
    649663        if bestMerge: 
    650664            ind1, ind2 = bestMerge 
    651665            currScore = bestScore 
    652             for i, l in enumerate(newAttr.getValueFrom.lookupTable): 
     666            for i, l in enumerate(newAttr.get_value_from.lookupTable): 
    653667                if not l.isSpecial() and int(l) == ind1: 
    654                     newAttr.getValueFrom.lookupTable[i] = ind2 
     668                    newAttr.get_value_from.lookupTable[i] = ind2 
    655669            newAttr.values[ind2] = newAttr.values[ind2] + "+" + newAttr.values[ind1] 
    656670            del activeValues[activeValues.index(ind1)] 
     
    658672            break 
    659673 
    660     if not removeUnusedValues: 
     674    if not remove_unused_values: 
    661675        return newAttr 
    662676 
    663677    reducedAttr = orange.EnumVariable(newAttr.name, values = [newAttr.values[i] for i in activeValues]) 
    664     reducedAttr.getValueFrom = newAttr.getValueFrom 
    665     reducedAttr.getValueFrom.classVar = reducedAttr 
     678    reducedAttr.get_value_from = newAttr.get_value_from 
     679    reducedAttr.get_value_from.class_var = reducedAttr 
    666680    return reducedAttr 
    667681 
    668682###### 
    669683# from orngFSS 
    670 def attMeasure(data, measure=Relief(k=20, m=50)): 
     684@Orange.misc.deprecated_keywords({"measure": "score"}) 
     685def score_all(data, score=Relief(k=20, m=50)): 
    671686    """Assess the quality of features using the given measure and return 
    672687    a sorted list of tuples (feature name, measure). 
    673688 
    674689    :param data: data table should include a discrete class. 
    675     :type data: :obj:`Orange.data.table` 
    676     :param measure:  feature scoring function. Derived from 
    677       :obj:`Orange.feature.scoring.Measure`. Defaults to Defaults to  
    678       :obj:`Orange.feature.scoring.Relief` with k=20 and m=50. 
    679     :type measure: :obj:`Orange.feature.scoring.Measure`  
    680     :rtype: :obj:`list` a sorted list of tuples (feature name, score) 
     690    :type data: :obj:`Orange.data.Table` 
     691    :param score:  feature scoring function. Derived from 
     692      :obj:`~Orange.feature.scoring.Score`. Defaults to  
     693      :obj:`~Orange.feature.scoring.Relief` with k=20 and m=50. 
     694    :type measure: :obj:`~Orange.feature.scoring.Score`  
     695    :rtype: :obj:`list`; a sorted list of tuples (feature name, score) 
    681696 
    682697    """ 
    683698    measl=[] 
    684699    for i in data.domain.attributes: 
    685         measl.append((i.name, measure(i, data))) 
     700        measl.append((i.name, score(i, data))) 
    686701    measl.sort(lambda x,y:cmp(y[1], x[1])) 
    687     
    688 #  for i in measl: 
    689 #    print "%25s, %6.3f" % (i[0], i[1]) 
    690702    return measl 
  • orange/Orange/feature/selection.py

    r8042 r8506  
    11""" 
     2######################### 
     3Selection (``selection``) 
     4######################### 
    25 
    36.. index:: feature selection 
     
    165168import Orange.core as orange 
    166169 
    167 from Orange.feature.scoring import attMeasure 
     170from Orange.feature.scoring import score_all 
    168171 
    169172# from orngFSS 
    170173def bestNAtts(scores, N): 
    171174    """Return the best N features (without scores) from the list returned 
    172     by function :obj:`Orange.feature.scoring.attMeasure`. 
    173      
    174     :param scores: a list such as one returned by  
    175       :obj:`Orange.feature.scoring.attMeasure` 
     175    by :obj:`Orange.feature.scoring.score_all`. 
     176     
     177    :param scores: a list such as returned by  
     178      :obj:`Orange.feature.scoring.score_all` 
    176179    :type scores: list 
    177180    :param N: number of best features to select.  
     
    184187def attsAboveThreshold(scores, threshold=0.0): 
    185188    """Return features (without scores) from the list returned by 
    186     :obj:`Orange.feature.scoring.attMeasure` with score above or 
     189    :obj:`Orange.feature.scoring.score_all` with score above or 
    187190    equal to a specified threshold. 
    188191     
    189192    :param scores: a list such as one returned by 
    190       :obj:`Orange.feature.scoring.attMeasure` 
     193      :obj:`Orange.feature.scoring.score_all` 
    191194    :type scores: list 
    192195    :param threshold: score threshold for attribute selection. Defaults to 0. 
     
    205208    :type data: Orange.data.table 
    206209    :param scores: a list such as one returned by  
    207       :obj:`Orange.feature.scoring.attMeasure` 
     210      :obj:`Orange.feature.scoring.score_all` 
    208211    :type scores: list 
    209212    :param N: number of features to select 
     
    218221    """Construct and return a new set of examples that includes a class and  
    219222    features from the list returned by  
    220     :obj:`Orange.feature.scoring.attMeasure` that have the score above or  
     223    :obj:`Orange.feature.scoring.score_all` that have the score above or  
    221224    equal to a specified threshold. 
    222225     
     
    224227    :type data: Orange.data.table 
    225228    :param scores: a list such as one returned by 
    226       :obj:`Orange.feature.scoring.attMeasure`     
     229      :obj:`Orange.feature.scoring.score_all`     
    227230    :type scores: list 
    228231    :param threshold: score threshold for attribute selection. Defaults to 0. 
     
    253256     
    254257    """ 
    255     measl = attMeasure(data, measure) 
     258    measl = score_all(data, measure) 
    256259    while len(data.domain.attributes)>0 and measl[-1][1]<margin: 
    257260        data = selectBestNAtts(data, measl, len(data.domain.attributes)-1) 
    258261#        print 'remaining ', len(data.domain.attributes) 
    259         measl = attMeasure(data, measure) 
     262        measl = score_all(data, measure) 
    260263    return data 
    261264 
     
    304307 
    305308        """ 
    306         ma = attMeasure(data, self.measure) 
     309        ma = score_all(data, self.measure) 
    307310        return selectAttsAboveThresh(data, ma, self.threshold) 
    308311 
     
    327330        self.n = n 
    328331    def __call__(self, data): 
    329         ma = attMeasure(data, self.measure) 
     332        ma = score_all(data, self.measure) 
    330333        self.n = min(self.n, len(data.domain.attributes)) 
    331334        return selectBestNAtts(data, ma, self.n) 
  • orange/Orange/misc/__init__.py

    r9450 r9483  
    171171    return decorating_function 
    172172 
     173#from Orange.misc.render import contextmanager 
     174from contextlib import contextmanager 
     175 
     176@contextmanager 
     177def member_set(obj, name, val): 
     178    """ A context manager that sets member ``name`` on ``obj`` to ``val`` 
     179    and restores the previous value on exit.  
     180    """ 
     181    old_val = getattr(obj, name, val) 
     182    setattr(obj, name, val) 
     183    yield 
     184    setattr(obj, name, old_val) 
     185     
    173186 
    174187class recursion_limit(object): 
  • orange/Orange/misc/addons.py

    r9450 r9483  
    14641464        for name in os.listdir(dir): 
    14651465            addOnDir = os.path.join(dir, name) 
    1466             if not os.path.isdir(addOnDir): 
     1466            if not os.path.isdir(addOnDir) or name.startswith("."): 
    14671467                continue 
    14681468            try: 
  • orange/Orange/misc/environ.py

    r9450 r9483  
    5959`dataset_install_dir`: 
    6060    Directory with example data sets. 
     61 
     62`network_install_dir`: 
     63    Directory with example networks. 
    6164 
    6265`add_ons_dir`: 
     
    132135    doc_install_dir = os.path.join(install_dir, "doc")  
    133136    dataset_install_dir = os.path.join(install_dir, "doc", "datasets")  
     137    network_install_dir = os.path.join(install_dir, "doc", "networks") 
    134138 
    135139    canvas_install_dir = os.path.join(install_dir, "OrangeCanvas") 
     
    175179_ALL_DIR_OPTIONS = ["install_dir", "canvas_install_dir", 
    176180                    "widget_install_dir", "icons_install_dir", 
    177                     "doc_install_dir", "dataset_install_dir", "add_ons_dir", "add_ons_dir_user", 
     181                    "doc_install_dir", "dataset_install_dir",  
     182                    "network_install_dir", "add_ons_dir", "add_ons_dir_user", 
    178183                    "application_dir", "output_dir", "default_reports_dir", 
    179184                    "orange_settings_dir", "canvas_settings_dir", 
  • orange/Orange/misc/testing.py

    r8042 r9483  
    112112 
    113113CLASSIFICATION_DATASETS = ["iris", "brown-selected", "lenses", "monks-1"] 
    114 REGRESSION_DATASETS = ["housing", "auto-mpg"] 
     114REGRESSION_DATASETS = ["housing", "auto-mpg", "servo"] 
    115115CLASSLES_DATASETS =  ["water-treatment"] 
    116116ALL_DATASETS  = CLASSIFICATION_DATASETS + REGRESSION_DATASETS + CLASSLES_DATASETS 
     
    407407         
    408408        for ex in test: 
    409             if classifier(ex, orange.GetValue) != classifier_clone(ex, orange.GetValue): 
    410                 print classifier(ex, orange.GetBoth) , classifier_clone(ex, orange.GetBoth) 
    411                 print classifier(ex, orange.GetValue) , classifier_clone(ex, orange.GetValue) 
    412             self.assertEqual(classifier(ex, orange.GetValue), classifier_clone(ex, orange.GetValue), "Pickled and original classifier return a different value!") 
    413         self.assertTrue(all(classifier(ex, orange.GetValue) == classifier_clone(ex, orange.GetValue) for ex in test)) 
    414  
     409            if isinstance(dataset.domain.class_var, Orange.data.variable.Continuous): 
     410                self.assertAlmostEqual(classifier(ex, orange.GetValue).native(), 
     411                                       classifier_clone(ex, orange.GetValue).native(), 
     412                                       dataset.domain.class_var.number_of_decimals + 3, 
     413                                       "Pickled and original classifier return a different value!") 
     414            else: 
     415                self.assertEqual(classifier(ex, orange.GetValue), classifier_clone(ex, orange.GetValue), "Pickled and original classifier return a different value!") 
    415416 
    416417class MeasureAttributeTestCase(DataTestCase): 
     
    424425    """ MEASURE must be defined in the subclass 
    425426    """ 
     427     
     428    def setUp(self): 
     429        self.measure = self.MEASURE 
    426430             
    427431    @test_on_data 
     
    431435        scores = [] 
    432436        for attr in data.domain.attributes: 
    433             score = self.MEASURE(attr, data) 
     437            score = self.measure(attr, data) 
    434438#            self.assertTrue(score >= 0.0) 
    435439            scores.append(score) 
     
    442446        """ 
    443447        import cPickle 
    444         s = cPickle.dumps(self.MEASURE) 
     448        s = cPickle.dumps(self.measure) 
    445449        measure = cPickle.loads(s) 
    446450        # TODO: make sure measure computes the same scores as measure 
     
    452456    """  
    453457    PREPROCESSOR = None 
     458     
     459    def setUp(self): 
     460        self.preprocessor = self.PREPROCESSOR 
    454461 
    455462    @test_on_data 
     
    457464        """ Test preprocessor on dataset  
    458465        """ 
    459         newdata = self.PREPROCESSOR(dataset) 
     466        newdata = self.preprocessor(dataset) 
    460467         
    461468    def test_pickle(self): 
    462469        """ Test preprocessor pickling 
    463470        """ 
    464         if isinstance(self.PREPROCESSOR, type): 
    465             prep = self.PREPROCESSOR() # Test the default constructed 
     471        if isinstance(self.preprocessor, type): 
     472            prep = self.preprocessor() # Test the default constructed 
    466473            s = cPickle.dumps(prep) 
    467474            prep = cPickle.loads(s) 
    468475                 
    469         s = cPickle.dumps(self.PREPROCESSOR) 
     476        s = cPickle.dumps(self.preprocessor) 
    470477        prep = cPickle.loads(s) 
    471478         
    472              
     479         
     480from Orange.distance.instances import distance_matrix 
     481from Orange.misc import member_set 
     482 
     483 
     484class DistanceTestCase(DataTestCase): 
     485    """ Test orange.ExamplesDistance/Constructor 
     486    """ 
     487    DISTANCE_CONSTRUCTOR = None 
     488     
     489    def setUp(self): 
     490        self.distance_constructor = self.DISTANCE_CONSTRUCTOR 
     491         
     492    @test_on_data 
     493    def test_distance_on(self, dataset): 
     494        import numpy 
     495        indices = orange.MakeRandomIndices2(dataset, min(20, len(dataset))) 
     496        dataset = dataset.select(indices, 0) 
     497        with member_set(self.distance_constructor, "ignore_class", True): 
     498            mat = distance_matrix(dataset, self.distance_constructor) 
     499         
     500        m = numpy.array(list(mat)) 
     501        self.assertTrue((m >= 0.0).all()) 
     502         
     503        if dataset.domain.class_var: 
     504            with member_set(self.distance_constructor, "ignore_class", False): 
     505                mat = distance_matrix(dataset, self.distance_constructor) 
     506            m1 = numpy.array(list(mat)) 
     507            self.assertTrue((m1 != m).all() or dataset, "%r does not seem to respect the 'ignore_class' flag") 
     508         
    473509def test_case_script(path): 
    474510    """ Return a TestCase instance from a script in `path`. 
  • orange/Orange/network/network.py

    r9450 r9483  
    5858import numpy 
    5959import networkx as nx 
    60  
    6160import Orange 
    6261import orangeom 
    63  
    6462import readwrite 
    65  
    6663from networkx import algorithms  
    6764from networkx.classes import function 
    68  
    6965 
    7066class MdsTypeClass(): 
     
    7571 
    7672MdsType = MdsTypeClass() 
    77  
    7873 
    7974def _get_doc(doc): 
     
    202197     
    203198    def __init__(self, data=None, name='', **attr):   
    204         nx.Graph.__init__(self, data, name, **attr) 
     199        nx.Graph.__init__(self, data, name=name, **attr) 
    205200        BaseGraph.__init__(self) 
     201     
     202    def subgraph(self, nbunch): 
     203        G = nx.Graph.subgraph(self, nbunch) 
     204        items = self.items().get_items(G.nodes()) 
     205        G = G.to_orange_network() 
     206        G.set_items(items) 
     207        return G 
     208        # TODO: _links 
    206209     
    207210    __doc__ += _get_doc(nx.Graph.__doc__) 
     
    216219     
    217220    def __init__(self, data=None, name='', **attr): 
    218         nx.DiGraph.__init__(self, data, name, **attr) 
     221        nx.DiGraph.__init__(self, data, name=name, **attr) 
    219222        BaseGraph.__init__(self) 
    220223     
     
    230233     
    231234    def __init__(self, data=None, name='', **attr): 
    232         nx.MultiGraph.__init__(self, data, name, **attr) 
     235        nx.MultiGraph.__init__(self, data, name=name, **attr) 
    233236        BaseGraph.__init__(self) 
    234237     
     
    244247     
    245248    def __init__(self, data=None, name='', **attr): 
    246         nx.MultiDiGraph.__init__(self, data, name, **attr) 
     249        nx.MultiDiGraph.__init__(self, data, name=name, **attr) 
    247250        BaseGraph.__init__(self) 
    248251     
     
    881884    ########################################################################## 
    882885     
    883      
    884      
    885      
     886    def map_to_graph(self, graph): 
     887        nodes = sorted(graph.nodes()) 
     888        return dict((v, (self.coors[0][i], self.coors[1][i])) for i,v in \ 
     889                    enumerate(nodes)) 
     890     
     891class NxView(object): 
     892    """Network View 
     893     
     894    """ 
     895     
     896    def __init__(self, **attr): 
     897        self._network = None 
     898        self._nx_explorer = None 
     899         
     900    def set_nx_explorer(self, _nx_explorer): 
     901        self._nx_explorer = _nx_explorer 
     902         
     903    def init_network(self, graph): 
     904        return graph 
     905         
     906    def nodes_selected(self): 
     907        pass 
  • orange/Orange/preprocess/__init__.py

    r9450 r9483  
    161161    __reduce__ = _orange__reduce__ 
    162162     
    163     def __init__(self, zeroBased=True, multinomialTreatment=orange.DomainContinuizer.NValues, normalizeContinuous=False, **kwargs): 
     163    def __init__(self, zeroBased=True, multinomialTreatment=orange.DomainContinuizer.NValues, 
     164                 continuousTreatment=orange.DomainContinuizer.Leave, 
     165                 classTreatment=orange.DomainContinuizer.Ignore, 
     166                 **kwargs): 
    164167        self.zeroBased = zeroBased 
    165168        self.multinomialTreatment = multinomialTreatment 
    166         self.normalizeContinuous = normalizeContinuous 
     169        self.continuousTreatment = continuousTreatment 
     170        self.classTreatment = classTreatment 
    167171             
    168172    def __call__(self, data, weightId=0): 
    169173        continuizer = orange.DomainContinuizer(zeroBased=self.zeroBased, 
    170174                                               multinomialTreatment=self.multinomialTreatment, 
    171                                                normalizeContinuous=self.normalizeContinuous, 
    172                                                classTreatment=orange.DomainContinuizer.Ignore) 
     175                                               continuousTreatment=self.continuousTreatment, 
     176                                               classTreatment=self.classTreatment) 
    173177        c_domain = continuizer(data, weightId) 
    174178        return data.translate(c_domain) 
  • orange/Orange/projection/pca.py

    r9450 r9483  
    1111    principal components. This transformation is defined in such a way that the 
    1212    first variable has as high variance as possible. 
    13      
     13 
    1414    If data instances are provided to the constructor, the learning algorithm 
    1515    is called and the resulting classifier is returned instead of the learner. 
     
    4343    def __call__(self, dataset): 
    4444        """ 
    45         Perform a pca analysis on a dataset and return classifer that maps data 
     45        Perform a pca analysis on a dataset and return a classifer that maps data 
    4646        into principal component subspace. 
    4747        """ 
     
    147147    def __call__(self, dataset): 
    148148        if type(dataset) != Orange.data.Table: 
    149             dataset = Orange.data.Table(self.input_domain, [dataset]) 
     149            dataset = Orange.data.Table([dataset]) 
    150150 
    151151        X = dataset.to_numpy_MA("a")[0] 
     
    188188        #          for i, a in enumerate(self.input_domain.attributes) 
    189189        #          ]) 
    190         ]) if len(self.pc_domain) <= 16 else \ 
     190        ]) if len(self.pc_domain) <= ncomponents else \ 
    191191        "\n".join([ 
    192192        "PCA SUMMARY", 
     
    364364        else: 
    365365            plt.show() 
    366              
     366  
  • orange/OrangeCanvas/orngCanvas.pyw

    r7831 r8162  
    351351        #self.menuHelp.addAction("Orange Canvas Online Help", self.menuOpenOnlineCanvasHelp) 
    352352 
    353         if os.path.exists(os.path.join(self.orangeDir, r"updateOrange.py")): 
    354             self.menuHelp.addSeparator() 
    355             self.menuHelp.addAction("Check for updates", self.menuCheckForUpdates) 
     353#        if os.path.exists(os.path.join(self.orangeDir, r"updateOrange.py")): 
     354#            self.menuHelp.addSeparator() 
     355#            self.menuHelp.addAction("Check for updates", self.menuCheckForUpdates) 
    356356             
    357357        self.menuHelp.addSeparator() 
  • orange/OrangeCanvas/orngCanvasItems.py

    r8305 r9483  
    99WARNING = 1 
    1010 
    11 def _graphicsEffect(item): 
    12     if hasattr(item, "graphicsEffect"): 
    13         return item.graphicsEffect() 
    14     else: 
    15         return None 
     11#def _graphicsEffect(item): 
     12#    if hasattr(item, "graphicsEffect"): 
     13#        return item.graphicsEffect() 
     14#    else: 
     15#        return None 
    1616     
    1717class TempCanvasLine(QGraphicsPathItem): 
     
    2626        self.setPen(QPen(QColor(180, 180, 180), 3, Qt.SolidLine)) 
    2727         
    28         if qVersion() >= "4.6" and canvasDlg.settings["enableCanvasDropShadows"]: 
    29             effect = QGraphicsDropShadowEffect(self.scene()) 
    30             effect.setOffset(QPointF(0.0, 0.0)) 
    31             effect.setBlurRadius(7) 
    32             self.setGraphicsEffect(effect)         
     28#        if qVersion() >= "4.6" and canvasDlg.settings["enableCanvasDropShadows"]: 
     29#            effect = QGraphicsDropShadowEffect(self.scene()) 
     30#            effect.setOffset(QPointF(0.0, 0.0)) 
     31#            effect.setBlurRadius(7) 
     32#            self.setGraphicsEffect(effect)         
    3333         
    3434    def setStartWidget(self, widget): 
     
    120120        self.setAcceptHoverEvents(True) 
    121121        self.hoverState = False 
    122         if qVersion() >= "4.6" and canvasDlg.settings["enableCanvasDropShadows"]: 
    123             effect = QGraphicsDropShadowEffect(self.scene()) 
    124             effect.setOffset(QPointF(0.0, 0.0)) 
    125             effect.setBlurRadius(7) 
    126             self.setGraphicsEffect(effect) 
     122         
     123#        if qVersion() >= "4.6" and canvasDlg.settings["enableCanvasDropShadows"]: 
     124#            effect = QGraphicsDropShadowEffect(self.scene()) 
     125#            effect.setOffset(QPointF(0.0, 0.0)) 
     126#            effect.setBlurRadius(7) 
     127#            self.setGraphicsEffect(effect) 
     128#            self.prepareGeometryChange() 
     129             
    127130        if scene is not None: 
    128131            scene.addItem(self) 
     
    190193        return stroke.createStroke(self.path()) 
    191194     
    192     def boundingRect(self): 
    193         rect = QGraphicsPathItem.boundingRect(self) 
    194         if _graphicsEffect(self): 
    195             textRect = self.captionItem.boundingRect() ## Should work without this but for some reason if using graphics effects the text gets clipped 
    196             textRect.moveTo(self.captionItem.pos()) 
    197             return rect.united(textRect) 
    198         else: 
    199             return rect 
     195#    def boundingRect(self): 
     196#        rect = QGraphicsPathItem.boundingRect(self) 
     197#        if _graphicsEffect(self): 
     198#            textRect = self.captionItem.boundingRect() ## Should work without this but for some reason if using graphics effects the text gets clipped 
     199#            textRect.moveTo(self.captionItem.pos()) 
     200#            return rect.united(textRect) 
     201#        else: 
     202#            return rect 
    200203 
    201204    def paint(self, painter, option, widget = None): 
     
    212215 
    213216    def updateTooltip(self): 
    214         status = self.getEnabled() == 0 and " (Disabled)" or "" 
    215         string = "<nobr><b>" + self.outWidget.caption + "</b> --> <b>" + self.inWidget.caption + "</b>" + status + "</nobr><hr>Signals:<br>" 
    216         for (outSignal, inSignal) in self.getSignals(): 
    217             string += "<nobr> &nbsp; &nbsp; - " + outSignal + " --> " + inSignal + "</nobr><br>" 
    218         string = string[:-4] 
    219         self.setToolTip(string) 
    220  
    221         # print the text with the signals 
    222         self.caption = "\n".join([outSignal for (outSignal, inSignal) in self.getSignals()]) 
    223         self.captionItem.setHtml("<center>%s</center>" % self.caption.replace("\n", "<br/>")) 
    224         self.updatePainterPath() 
     217        if self.inWidget and self.outWidget: 
     218            status = self.getEnabled() == 0 and " (Disabled)" or "" 
     219            string = "<nobr><b>" + self.outWidget.caption + "</b> --> <b>" + self.inWidget.caption + "</b>" + status + "</nobr><hr>Signals:<br>" 
     220            for (outSignal, inSignal) in self.getSignals(): 
     221                string += "<nobr> &nbsp; &nbsp; - " + outSignal + " --> " + inSignal + "</nobr><br>" 
     222            string = string[:-4] 
     223            self.setToolTip(string) 
     224     
     225            # print the text with the signals 
     226            self.caption = "\n".join([outSignal for (outSignal, inSignal) in self.getSignals()]) 
     227            self.captionItem.setHtml("<center>%s</center>" % self.caption.replace("\n", "<br/>")) 
     228            self.updatePainterPath() 
    225229 
    226230    def hoverEnterEvent(self, event): 
     
    305309        self.setFlags(QGraphicsItem.ItemIsSelectable)# | QGraphicsItem.ItemIsMovable) 
    306310         
    307         if qVersion() >= "4.6" and self.canvasDlg.settings["enableCanvasDropShadows"]: 
    308             effect = QGraphicsDropShadowEffect() 
    309             effect.setOffset(QPointF(1.1, 3.1)) 
    310             effect.setBlurRadius(7) 
    311             self.setGraphicsEffect(effect) 
     311#        if qVersion() >= "4.6" and self.canvasDlg.settings["enableCanvasDropShadows"]: 
     312#            effect = QGraphicsDropShadowEffect() 
     313#            effect.setOffset(QPointF(1.1, 3.1)) 
     314#            effect.setBlurRadius(7) 
     315#            self.setGraphicsEffect(effect) 
     316#            self.prepareGeometryChange() 
    312317             
    313318        if scene is not None: 
     
    431436        rect = QRectF(QPointF(0, 0), self.widgetSize).adjusted(-11, -6, 11, 6)#.adjusted(-100, -100, 100, 100) #(-10-width, -4, +10+width, +25) 
    432437        rect.setTop(rect.top() - 20 - 21) ## Room for progress bar and warning, error, info icons 
    433         if _graphicsEffect(self): 
    434             textRect = self.captionItem.boundingRect() ## Should work without this but for some reason if using graphics effects the text gets clipped 
    435             textRect.moveTo(self.captionItem.pos()) 
    436             return rect.united(textRect) 
    437         else: 
    438             return rect  
     438#        if _graphicsEffect(self): 
     439#            textRect = self.captionItem.boundingRect() ## Should work without this but for some reason if using graphics effects the text gets clipped 
     440#            textRect.moveTo(self.captionItem.pos())  
     441        return rect 
    439442 
    440443    # is mouse position inside the left signal channel 
  • orange/OrangeCanvas/orngDlgs.py

    r8042 r8147  
    461461        generalBox = OWGUI.widgetBox(GeneralTab, "General Options") 
    462462        self.snapToGridCB = OWGUI.checkBox(generalBox, self.settings, "snapToGrid", "Snap widgets to grid", debuggingEnabled = 0) 
    463         self.enableCanvasDropShadowsCB = OWGUI.checkBox(generalBox, self.settings, "enableCanvasDropShadows", "Enable drop shadows in canvas", debuggingEnabled = 0) 
     463#        self.enableCanvasDropShadowsCB = OWGUI.checkBox(generalBox, self.settings, "enableCanvasDropShadows", "Enable drop shadows in canvas", debuggingEnabled = 0) 
    464464        self.writeLogFileCB  = OWGUI.checkBox(generalBox, self.settings, "writeLogFile", "Save content of the Output window to a log file", debuggingEnabled = 0) 
    465465        self.showSignalNamesCB = OWGUI.checkBox(generalBox, self.settings, "showSignalNames", "Show signal names between widgets", debuggingEnabled = 0) 
  • orange/OrangeCanvas/orngDoc.py

    r8052 r9483  
    7979        else: 
    8080            ce.ignore() 
     81            return 
    8182             
    8283        QWidget.closeEvent(self, ce) 
     
    341342            return 
    342343         
    343         with self.signalManager.freeze(): 
    344             while widget.inLines != []: self.removeLine1(widget.inLines[0]) 
    345             while widget.outLines != []:  self.removeLine1(widget.outLines[0]) 
     344        #with self.signalManager.freeze(): 
     345        while widget.inLines != []: self.removeLine1(widget.inLines[0]) 
     346        while widget.outLines != []:  self.removeLine1(widget.outLines[0]) 
    346347     
    347             self.signalManager.removeWidget(widget.instance) 
     348        self.signalManager.removeWidget(widget.instance) 
    348349             
    349350        self.widgets.remove(widget) 
  • orange/OrangeCanvas/orngView.py

    r8042 r8124  
    163163    def resetLineSignals(self): 
    164164        if self.selectedLine: 
    165             self.doc.resetActiveSignals(self.selectedLine.outWidget, self.selectedLine.inWidget, enabled = self.doc.signalManager.getLinkEnabled(self.selectedLine.outWidget.instance, self.selectedLine.inWidget.instance)) 
    166             self.selectedLine.inWidget.updateTooltip() 
    167             self.selectedLine.outWidget.updateTooltip() 
     165            outWidget, inWidget = self.selectedLine.outWidget, self.selectedLine.inWidget 
     166            self.doc.resetActiveSignals(outWidget, inWidget, enabled = self.doc.signalManager.getLinkEnabled(outWidget.instance, inWidget.instance)) 
     167            inWidget.updateTooltip() 
     168            outWidget.updateTooltip() 
    168169            self.selectedLine.updateTooltip() 
    169170 
     
    391392                QMessageBox.information( self, "Orange Canvas", "Please wait until Orange finishes processing signals.") 
    392393                return 
    393             self.doc.resetActiveSignals(activeItem.outWidget, activeItem.inWidget, enabled = self.doc.signalManager.getLinkEnabled(activeItem.outWidget.instance, activeItem.inWidget.instance)) 
    394             activeItem.inWidget.updateTooltip() 
    395             activeItem.outWidget.updateTooltip() 
     394            inWidget, outWidget = activeItem.inWidget, activeItem.outWidget 
     395            self.doc.resetActiveSignals(outWidget, inWidget, enabled = self.doc.signalManager.getLinkEnabled(outWidget.instance, inWidget.instance)) 
     396            inWidget.updateTooltip() 
     397            outWidget.updateTooltip() 
    396398            activeItem.updateTooltip() 
    397399             
  • orange/OrangeWidgets/Classify/OWCN2RulesViewer.py

    r9450 r9483  
    342342            self.tableView.horizontalHeader().setSectionHidden(i, not visible) 
    343343            anyVisible = anyVisible or visible 
    344         self.reportButton.setEnabled(anyVisible) 
     344         
     345        # report button is not available if not running canvas 
     346        if hasattr(self, "reportButton"): 
     347            self.reportButton.setEnabled(anyVisible) 
    345348 
    346349     
  • orange/OrangeWidgets/Data/OWSave.py

    r8042 r8094  
    8383            startfile = self.recentFiles[0] 
    8484        else: 
    85             startfile = "." 
     85            startfile = os.path.expanduser("~/") 
    8686 
    8787#        filename, selectedFilter = QFileDialog.getSaveFileNameAndFilter(self, 'Save Orange Data File', startfile, 
  • orange/OrangeWidgets/Evaluate/OWTestLearners.py

    r9482 r9483  
    3939        self.show = show 
    4040        self.cmBased = cmBased 
     41         
     42def dispatch(score_desc, res, cm): 
     43    """ Dispatch the call to orngStat method. 
     44    """ 
     45    return eval("orngStat." + score_desc.f) 
     46 
    4147 
    4248class OWTestLearners(OWWidget): 
     
    376382            res = orngTest.learnAndTestOnTestData(learners, self.data, self.testdata, storeExamples = True, callback=pb.advance) 
    377383            pb.finish() 
     384             
    378385        if self.isclassification(): 
    379386            cm = orngStat.computeConfusionMatrices(res, classIndex = self.targetClass) 
     387        else: 
     388            cm = None 
    380389 
    381390        if self.preprocessor: # Unwrap learners  
     
    390399        self.error(range(len(self.stat))) 
    391400        scores = [] 
     401         
     402         
     403         
    392404        for i, s in enumerate(self.stat): 
    393             try: 
    394                 scores.append(eval("orngStat." + s.f)) 
    395             except Exception, ex: 
    396                 self.error(i, "An error occurred while evaluating orngStat." + s.f + "on %s due to %s" % \ 
    397                            (" ".join([l.name for l in learners]), ex.message)) 
    398                 scores.append([None] * len(self.learners)) 
     405            if s.cmBased: 
     406                try: 
     407#                    scores.append(eval("orngStat." + s.f)) 
     408                    scores.append(dispatch(s, res, cm)) 
     409                except Exception, ex: 
     410                    self.error(i, "An error occurred while evaluating orngStat." + s.f + "on %s due to %s" % \ 
     411                               (" ".join([l.name for l in learners]), ex.message)) 
     412                    scores.append([None] * len(self.learners)) 
     413            else: 
     414                scores_one = [] 
     415                for res_one in orngStat.split_by_classifiers(res): 
     416                    try: 
     417#                        scores_one.append(eval("orngStat." + s.f)[0]) 
     418                        scores_one.extend(dispatch(s, res_one, cm)) 
     419                    except Exception, ex: 
     420                        self.error(i, "An error occurred while evaluating orngStat." + s.f + "on %s due to %s" % \ 
     421                                   (res.classifierNames[0], ex.message)) 
     422                        scores_one.append(None) 
     423                scores.append(scores_one) 
    399424                 
    400         for (i, l) in enumerate(learners): 
     425        for i, l in enumerate(learners): 
    401426            self.learners[l.id].scores = [s[i] if s else None for s in scores] 
    402427             
  • orange/OrangeWidgets/OWGUI.py

    r9450 r9483  
    18511851        self.initStyleOption(option, index) 
    18521852        textRect = style.subElementRect(QStyle.SE_ItemViewItemText, option) 
     1853        if not textRect.isValid(): 
     1854            textRect = option.rect 
    18531855        margin = style.pixelMetric(QStyle.PM_FocusFrameHMargin, option) + 1 
    18541856        textRect = textRect.adjusted(margin, 0, -margin, 0) 
     
    18991901            text = self.displayText(index.data(Qt.DisplayRole), QLocale.system()) 
    19001902            textRect = style.subElementRect(QStyle.SE_ItemViewItemText, option) 
     1903            if not textRect.isValid(): 
     1904                textRect = option.rect 
    19011905            margin = style.pixelMetric(QStyle.PM_FocusFrameHMargin, option) + 1 
    19021906            textRect = textRect.adjusted(margin, 0, -margin, 0) 
  • orange/OrangeWidgets/Unsupervised/OWNetClustering.py

    r8305 r9483  
    11""" 
    2 <name>Network Clustering</name> 
    3 <description>Orange widget for community detection in networks</description> 
    4 <icon>icons/Network.png</icon> 
    5 <contact>Miha Stajdohar (miha.stajdohar(@at@)gmail.com)</contact>  
    6 <priority>7440</priority> 
     2THIS WIDGET IS OBSOLETE; USE OWNxClustering.py 
    73""" 
    84 
  • orange/OrangeWidgets/Unsupervised/OWNetExplorer.py

    r9450 r9483  
    11""" 
    2 <name>Net Explorer</name> 
    3 <description>Orange widget for network exploration.</description> 
    4 <icon>icons/Network.png</icon> 
    5 <contact>Miha Stajdohar (miha.stajdohar(@at@)gmail.com)</contact>  
    6 <priority>7420</priority> 
     2THIS WIDGET IS OBSOLETE; USE OWNxExplorer.py 
    73""" 
    84import orange 
  • orange/OrangeWidgets/Unsupervised/OWNetworkFile.py

    r8305 r9483  
    11""" 
    2 <name>Network File</name> 
    3 <description>Reads data from a graf file (Pajek networks (.net) files and GML network files).</description> 
    4 <icon>icons/NetworkFile.png</icon> 
    5 <contact>Miha Stajdohar (miha.stajdohar(@at@)gmail.com)</contact>  
    6 <priority>7410</priority> 
     2THIS WIDGET IS OBSOLETE; USE OWNxFile.py 
    73""" 
    84 
  • orange/OrangeWidgets/Unsupervised/OWNetworkFromDistances.py

    r8305 r9483  
    11""" 
    2 <name>Network from Distances</name> 
    3 <description>Costructs Graph object by connecting nodes from ExampleTable where distance between them is between given threshold.</description> 
    4 <icon>icons/NetworkFromDistances.png</icon> 
    5 <contact>Miha Stajdohar (miha.stajdohar(@at@)gmail.com)</contact>  
    6 <priority>7430</priority> 
     2THIS WIDGET IS OBSOLETE; USE OWNxFromDistances.py 
    73""" 
    84 
  • orange/OrangeWidgets/Unsupervised/OWNxCanvas.py

    r9450 r9483  
    1515from orngScaleScatterPlotData import * 
    1616 
    17 class NetworkVertex(): 
     17class NodeItem(): 
    1818    def __init__(self, index=-1): 
    1919        self.index = index 
     
    3434        self.style = 1 
    3535     
    36 class NetworkEdge(): 
     36class EdgeItem(): 
    3737    def __init__(self, u=None, v=None, weight=0, arrowu=0, arrowv=0,  
    3838                 links_index=None, label=[]): 
     
    5252      QwtPlotCurve.__init__(self, "Network Curve") 
    5353 
    54       self.coors = None 
    55       self.vertices = [] 
     54      self.coors = {} 
     55      self.vertices = {} 
    5656      self.edges = [] 
    5757      self.setItemAttribute(QwtPlotItem.Legend, 0) 
    5858      self.showEdgeLabels = 0 
    5959 
    60   def moveSelectedVertices(self, dx, dy): 
    61     selected = self.getSelectedVertices() 
     60  def move_selected_nodes(self, dx, dy): 
     61    selected = self.get_selected_nodes() 
    6262     
    6363    self.coors[0][selected] = self.coors[0][selected] + dx 
     
    6767    return selected 
    6868   
    69   def setVertexColor(self, v, color): 
     69  def set_node_color(self, v, color): 
    7070      pen = self.vertices[v].pen 
    7171      self.vertices[v].color = color 
    7272      self.vertices[v].pen = QPen(color, pen.width()) 
     73 
     74  def set_nodes_color(self, vertices, color): 
     75      for v in vertices: 
     76          v.color = color 
     77          v.pen = QPen(color, v.pen.width()) 
    7378       
    74   def setEdgeColor(self, index, color, nocolor=0): 
     79  def set_edge_color(self, index, color, nocolor=0): 
    7580      pen = self.edges[index].pen 
    7681      if nocolor: 
     
    7984      self.edges[index].pen.setCapStyle(Qt.RoundCap) 
    8085   
    81   def getSelectedVertices(self): 
    82     return [vertex.index for vertex in self.vertices if vertex.selected] 
    83  
    84   def getUnselectedVertices(self): 
    85     return [vertex.index for vertex in self.vertices if not vertex.selected] 
    86  
    87   def getMarkedVertices(self): 
    88     return [vertex.index for vertex in self.vertices if vertex.marked] 
     86  def get_selected_nodes(self): 
     87    return [vertex.index for vertex in self.vertices.itervalues() if vertex.selected] 
     88 
     89  def get_unselected_nodes(self): 
     90    return [vertex.index for vertex in self.vertices.itervalues() if not vertex.selected] 
     91 
     92  def get_marked_nodes(self): 
     93    return [vertex.index for vertex in self.vertices.itervalues() if vertex.marked] 
    8994   
    90   def setMarkedVertices(self, vertices): 
    91     for vertex in self.vertices: 
     95  def set_marked_nodes(self, vertices): 
     96    for vertex in self.vertices.itervalues(): 
    9297      if vertex.index in vertices: 
    9398        vertex.marked = True 
     
    95100        vertex.marked = False 
    96101         
    97   def markToSel(self): 
    98     for vertex in self.vertices: 
     102  def mark_to_sel(self): 
     103    for vertex in self.vertices.itervalues(): 
    99104      if vertex.marked == True: 
    100105          vertex.selected = True 
    101106           
    102   def selToMark(self): 
    103     for vertex in self.vertices: 
     107  def sel_to_mark(self): 
     108    for vertex in self.vertices.itervalues(): 
    104109      if vertex.selected == True: 
    105110          vertex.selected = False 
    106111          vertex.marked = True 
    107112   
    108   def unMark(self): 
    109     for vertex in self.vertices: 
     113  def unmark(self): 
     114    for vertex in self.vertices.itervalues(): 
    110115      vertex.marked = False 
    111116       
    112   def unSelect(self): 
    113     for vertex in self.vertices: 
     117  def unselect(self): 
     118    for vertex in self.vertices.itervalues(): 
    114119        vertex.selected = False 
    115120         
    116   def setHiddenVertices(self, nodes): 
    117     for vertex in self.vertices: 
     121  def set_hidden_nodes(self, nodes): 
     122    for vertex in self.vertices.itervalues(): 
    118123      if vertex.index in nodes: 
    119124        vertex.show = False 
     
    121126        vertex.show = True 
    122127       
    123   def hideSelectedVertices(self): 
    124     for vertex in self.vertices: 
     128  def hide_selected_nodes(self): 
     129    for vertex in self.vertices.itervalues(): 
    125130      if vertex.selected: 
    126131        vertex.show = False 
    127132   
    128   def hideUnSelectedVertices(self): 
    129     for vertex in self.vertices: 
     133  def hide_unselected_nodes(self): 
     134    for vertex in self.vertices.itervalues(): 
    130135      if not vertex.selected: 
    131136        vertex.show = False 
    132137     
    133   def showAllVertices(self): 
    134     for vertex in self.vertices: 
     138  def show_all_vertices(self): 
     139    for vertex in self.vertices.itervalues(): 
    135140      vertex.show = True 
    136141     
     
    143148        painter.setPen(edge.pen) 
    144149 
    145         px1 = xMap.transform(self.coors[0][edge.u.index])   #ali pa tudi self.x1, itd 
    146         py1 = yMap.transform(self.coors[1][edge.u.index]) 
    147         px2 = xMap.transform(self.coors[0][edge.v.index]) 
    148         py2 = yMap.transform(self.coors[1][edge.v.index]) 
     150        px1 = xMap.transform(self.coors[edge.u.index][0])   #ali pa tudi self.x1, itd 
     151        py1 = yMap.transform(self.coors[edge.u.index][1]) 
     152        px2 = xMap.transform(self.coors[edge.v.index][0]) 
     153        py2 = yMap.transform(self.coors[edge.v.index][1]) 
    149154         
    150155        painter.drawLine(px1, py1, px2, py2) 
     
    185190            painter.drawText(r, Qt.AlignHCenter + Qt.AlignVCenter, lbl) 
    186191     
    187     for vertex in self.vertices: 
     192    for key, vertex in self.vertices.iteritems(): 
    188193      if vertex.show: 
    189         pX = xMap.transform(self.coors[0][vertex.index])   #dobimo koordinati v pikslih (tipa integer) 
    190         pY = yMap.transform(self.coors[1][vertex.index])   #ki se stejeta od zgornjega levega kota canvasa 
     194        pX = xMap.transform(self.coors[vertex.index][0])   #dobimo koordinati v pikslih (tipa integer) 
     195        pY = yMap.transform(self.coors[vertex.index][1])   #ki se stejeta od zgornjega levega kota canvasa 
    191196        if vertex.selected:     
    192197          painter.setPen(QPen(Qt.yellow, 3)) 
     
    205210          painter.drawEllipse(rect) 
    206211         
     212  def closest_node(self, px, py): 
     213    ndx = min(self.coors, key=lambda x: abs(self.coors[x][0]-px) + abs(self.coors[x][1]-py)) 
     214    return ndx, math.sqrt((self.coors[ndx][0]-px)**2 + (self.coors[ndx][0]-px)**2) 
     215 
     216  def get_nodes_in_rect(self, x1, y1, x2, y2): 
     217      if x1 > x2: 
     218          x1, x2 = x2, x1 
     219      if y1 > y2: 
     220          y1, y2 = y2, y1 
     221      return [key for key in self.coors if x1 < self.coors[key][0] < x2 and y1 < self.coors[key][1] < y2] 
     222         
    207223class OWNxCanvas(OWGraph): 
    208224    def __init__(self, master, parent=None, name="None"): 
     
    212228        self.labelText = [] 
    213229        self.tooltipText = [] 
    214         self.vertices_old = {}         # distionary of nodes (orngIndex: vertex_objekt) 
    215         self.edges_old = {}            # distionary of edges (curveKey: edge_objekt) 
    216         self.vertices = [] 
    217         self.edges = [] 
     230        #self.vertices_old = {}         # distionary of nodes (orngIndex: vertex_objekt) 
     231        #self.edges_old = {}            # distionary of edges (curveKey: edge_objekt) 
     232        #self.vertices = [] 
     233        #self.edges = [] 
    218234        self.indexPairs = {}       # distionary of type CurveKey: orngIndex   (for nodes) 
    219235        #self.selection = []        # list of selected nodes (indices) 
     
    274290        self.controlPressed = False 
    275291        self.altPressed = False 
     292        self.items = None 
     293        self.links = None 
    276294         
    277295        self.setFocusPolicy(Qt.StrongFocus) 
    278296         
    279297    def getSelection(self): 
    280       return self.networkCurve.getSelectedVertices() 
    281      
    282     def getMarkedVertices(self): 
    283       return self.networkCurve.getMarkedVertices() 
     298      return self.networkCurve.get_selected_nodes() 
     299     
     300    def get_marked_nodes(self): 
     301      return self.networkCurve.get_marked_nodes() 
    284302         
    285303    def getVertexSize(self, index): 
    286304        return 6 
    287305         
    288     def setHiddenVertices(self, nodes): 
    289         self.networkCurve.setHiddenVertices(nodes) 
    290      
    291     def hideSelectedVertices(self): 
    292       self.networkCurve.hideSelectedVertices() 
     306    def set_hidden_nodes(self, nodes): 
     307        self.networkCurve.set_hidden_nodes(nodes) 
     308     
     309    def hide_selected_nodes(self): 
     310      self.networkCurve.hide_selected_nodes() 
    293311      self.drawPlotItems() 
    294312       
    295     def hideUnSelectedVertices(self): 
    296       self.networkCurve.hideUnSelectedVertices() 
     313    def hide_unselected_nodes(self): 
     314      self.networkCurve.hide_unselected_nodes() 
    297315      self.drawPlotItems() 
    298316       
    299     def showAllVertices(self): 
    300       self.networkCurve.showAllVertices() 
     317    def show_all_vertices(self): 
     318      self.networkCurve.show_all_vertices() 
    301319      self.drawPlotItems() 
    302320       
     
    329347                 
    330348    def markedToSelection(self): 
    331         self.networkCurve.markToSel() 
     349        self.networkCurve.mark_to_sel() 
    332350        self.drawPlotItems() 
    333351         
    334352    def selectionToMarked(self): 
    335         self.networkCurve.selToMark() 
     353        self.networkCurve.sel_to_mark() 
    336354        self.drawPlotItems() 
    337355         
    338356        if self.sendMarkedNodes != None: 
    339             self.sendMarkedNodes(self.networkCurve.getMarkedVertices()) 
     357            self.sendMarkedNodes(self.networkCurve.get_marked_nodes()) 
    340358         
    341359    def removeSelection(self, replot=True): 
    342         self.networkCurve.unSelect() 
     360        self.networkCurve.unselect() 
    343361         
    344362        if replot: 
     
    356374         
    357375    def getSelectedExamples(self): 
    358         selection = self.networkCurve.getSelectedVertices() 
    359          
    360         if len(selection) == 0: 
    361             return None 
    362          
    363         if self.graph.items() is not None: 
    364             return self.graph.items().getitems(selection) 
    365         else: 
    366             return None 
     376        return self.networkCurve.get_selected_nodes() 
    367377         
    368378    def getUnselectedExamples(self): 
    369         unselection = self.networkCurve.getUnselectedVertices() 
    370          
    371         if len(unselection) == 0: 
    372             return None 
    373          
    374         if self.graph.items() is not None: 
    375             return self.graph.items().getitems(unselection) 
    376         else: 
    377             return None 
     379        return self.networkCurve.get_unselected_nodes() 
    378380     
    379381    def getSelectedGraph(self): 
    380       selection = self.networkCurve.getSelectedVertices() 
     382      selection = self.networkCurve.get_selected_nodes() 
    381383       
    382384      if len(selection) == 0: 
     
    387389      return subnet 
    388390     
    389     def getSelectedVertices(self): 
    390       return self.networkCurve.getSelectedVertices() 
     391    def get_selected_nodes(self): 
     392      return self.networkCurve.get_selected_nodes() 
    391393     
    392394    def getNeighboursUpTo(self, ndx, dist): 
     
    403405        if not self.freezeNeighbours and self.selectionNeighbours: 
    404406            toMark = set() 
    405             for ndx in self.networkCurve.getSelectedVertices(): 
     407            for ndx in self.networkCurve.get_selected_nodes(): 
    406408                toMark |= self.getNeighboursUpTo(ndx, self.selectionNeighbours) 
    407409             
    408             self.networkCurve.setMarkedVertices(toMark) 
     410            self.networkCurve.set_marked_nodes(toMark) 
    409411            self.drawPlotItems() 
    410412                 
    411413        elif not self.freezeNeighbours and self.selectionNeighbours == 0: 
    412             self.networkCurve.setMarkedVertices(self.networkCurve.getSelectedVertices()) 
     414            self.networkCurve.set_marked_nodes(self.networkCurve.get_selected_nodes()) 
    413415            self.drawPlotItems() 
    414416             
    415417        if self.sendMarkedNodes != None: 
    416             self.sendMarkedNodes(self.networkCurve.getMarkedVertices()) 
    417                  
    418     def unMark(self): 
    419       self.networkCurve.unMark() 
     418            self.sendMarkedNodes(self.networkCurve.get_marked_nodes()) 
     419                 
     420    def unmark(self): 
     421      self.networkCurve.unmark() 
    420422      self.drawPlotItems(replot=0) 
    421423       
     
    423425            self.sendMarkedNodes([]) 
    424426             
    425     def setMarkedVertices(self, vertices): 
    426       self.networkCurve.setMarkedVertices(vertices) 
     427    def set_marked_nodes(self, vertices): 
     428      self.networkCurve.set_marked_nodes(vertices) 
    427429      self.drawPlotItems(replot=0) 
    428430       
    429431      if self.sendMarkedNodes != None: 
    430             self.sendMarkedNodes(self.networkCurve.getMarkedVertices()) 
     432            self.sendMarkedNodes(self.networkCurve.get_marked_nodes()) 
    431433         
    432434    def activateMoveSelection(self): 
     
    443445            dx = newX - self.invTransform(2, self.GMmouseMoveEvent.x()) 
    444446            dy = newY - self.invTransform(0, self.GMmouseMoveEvent.y()) 
    445             movedVertices = self.networkCurve.moveSelectedVertices(dx, dy) 
     447            movedVertices = self.networkCurve.move_selected_nodes(dx, dy) 
    446448             
    447449            self.GMmouseMoveEvent.setX(event.pos().x())  #zacetni dogodek postane trenutni 
     
    457459            px = self.invTransform(2, event.x()) 
    458460            py = self.invTransform(0, event.y())    
    459             ndx, mind = self.layout.closest_vertex(px, py) 
    460             dX = self.transform(QwtPlot.xBottom, self.layout.coors[0][ndx]) - event.x() 
    461             dY = self.transform(QwtPlot.yLeft,   self.layout.coors[1][ndx]) - event.y() 
     461            ndx, mind = self.networkCurve.closest_node(px, py) 
     462            dX = self.transform(QwtPlot.xBottom, self.networkCurve.coors[ndx][0]) - event.x() 
     463            dY = self.transform(QwtPlot.yLeft,   self.networkCurve.coors[ndx][1]) - event.y() 
    462464            # transform to pixel distance 
    463465            distance = math.sqrt(dX**2 + dY**2)  
    464466               
    465             if ndx != -1 and distance <= self.vertices[ndx].size / 2: 
     467            if ndx != -1 and distance <= self.networkCurve.vertices[ndx].size: 
    466468                toMark = set(self.getNeighboursUpTo(ndx, self.tooltipNeighbours)) 
    467                 self.networkCurve.setMarkedVertices(toMark) 
     469                self.networkCurve.set_marked_nodes(toMark) 
    468470                self.drawPlotItems() 
    469471                 
    470472                if self.sendMarkedNodes != None: 
    471                     self.sendMarkedNodes(self.networkCurve.getMarkedVertices()) 
     473                    self.sendMarkedNodes(self.networkCurve.get_marked_nodes()) 
    472474            else: 
    473                 self.networkCurve.unMark() 
     475                self.networkCurve.unmark() 
    474476                self.drawPlotItems() 
    475477                 
     
    478480         
    479481        if self.showDistances: 
    480             selection = self.networkCurve.getSelectedVertices() 
     482            selection = self.networkCurve.get_selected_nodes() 
    481483            if len(selection) > 0: 
    482484                px = self.invTransform(2, event.x()) 
    483485                py = self.invTransform(0, event.y())   
    484486                  
    485                 v, mind = self.layout.closest_vertex(px, py) 
    486                 dX = self.transform(QwtPlot.xBottom, self.layout.coors[0][v]) - event.x() 
    487                 dY = self.transform(QwtPlot.yLeft,   self.layout.coors[1][v]) - event.y() 
     487                v, mind = self.networkCurve.closest_node(px, py) 
     488                dX = self.transform(QwtPlot.xBottom, self.networkCurve.coors[v][0]) - event.x() 
     489                dY = self.transform(QwtPlot.yLeft,   self.networkCurve.coors[v][1]) - event.y() 
    488490                # transform to pixel distance 
    489491                distance = math.sqrt(dX**2 + dY**2)                
    490                 if v != -1 and distance <= self.vertices[v].size / 2: 
     492                if v != -1 and distance <= self.networkCurve.vertices[v].size: 
    491493                    if self.items_matrix == None: 
    492494                        dst = 'vertex distance signal not set' 
     
    557559            elif self.mouseSelectedVertex == 0: 
    558560                  
    559                 selection = self.layout.get_vertices_in_rect(x1, y1, x2, y2) 
     561                selection = self.networkCurve.get_nodes_in_rect(x1, y1, x2, y2) 
    560562     
    561563                def selectVertex(ndx): 
    562                     if self.vertices[ndx].show: 
    563                         self.vertices[ndx].selected = True 
     564                    if self.networkCurve.vertices[ndx].show: 
     565                        self.networkCurve.vertices[ndx].selected = True 
    564566                         
    565567                map(selectVertex, selection) 
     
    567569                if len(selection) == 0 and x1 == x2 and y1 == y2: 
    568570                    self.removeSelection() 
    569                     self.unMark() 
     571                    self.unmark() 
    570572             
    571573                self.markSelectionNeighbours() 
     
    591593           
    592594        if e.key() == 87 or e.key() == 81: 
    593             selection = [v.index for v in self.vertices if v.selected] 
     595            selection = [v.index for v in self.networkCurve.vertices.itervalues() if v.selected] 
    594596            if len(selection) > 0: 
    595597                phi = [math.pi / -180 if e.key() == 87 else math.pi / 180] 
     
    617619        OWGraph.keyReleaseEvent(self, e) 
    618620         
    619      
    620621    def clickedSelectedOnVertex(self, pos): 
    621622        min = 1000000 
     
    625626        py = self.invTransform(0, pos.y())    
    626627     
    627         ndx, min = self.layout.closest_vertex(px, py) 
    628         dX = self.transform(QwtPlot.xBottom, self.layout.coors[0][ndx]) - pos.x() 
    629         dY = self.transform(QwtPlot.yLeft,   self.layout.coors[1][ndx]) - pos.y() 
     628        ndx, min = self.networkCurve.closest_node(px, py) 
     629        dX = self.transform(QwtPlot.xBottom, self.networkCurve.coors[ndx][0]) - pos.x() 
     630        dY = self.transform(QwtPlot.yLeft,   self.networkCurve.coors[ndx][1]) - pos.y() 
    630631        # transform to pixel distance 
    631632        distance = math.sqrt(dX**2 + dY**2) 
    632         if ndx != -1 and distance <= self.vertices[ndx].size / 2: 
    633             return self.vertices[ndx].selected 
     633         
     634        #self.networkCurve 
     635         
     636        if ndx != -1 and distance <= self.networkCurve.vertices[ndx].size: 
     637            return self.networkCurve.vertices[ndx].selected 
    634638        else: 
    635639            return False 
     
    642646        py = self.invTransform(0, pos.y())    
    643647     
    644         ndx, min = self.layout.closest_vertex(px, py) 
    645         dX = self.transform(QwtPlot.xBottom, self.layout.coors[0][ndx]) - pos.x() 
    646         dY = self.transform(QwtPlot.yLeft,   self.layout.coors[1][ndx]) - pos.y() 
     648        ndx, min = self.networkCurve.closest_node(px, py) 
     649        dX = self.transform(QwtPlot.xBottom, self.networkCurve.coors[ndx][0]) - pos.x() 
     650        dY = self.transform(QwtPlot.yLeft,   self.networkCurve.coors[ndx][1]) - pos.y() 
    647651        # transform to pixel distance 
    648652        distance = math.sqrt(dX**2 + dY**2) 
    649         if ndx != -1 and distance <= self.vertices[ndx].size / 2: 
     653        if ndx != -1 and distance <= self.networkCurve.vertices[ndx].size: 
    650654            return True 
    651655        else: 
     
    659663        py = self.invTransform(0, pos.y())    
    660664     
    661         ndx, min = self.layout.closest_vertex(px, py) 
    662          
    663         dX = self.transform(QwtPlot.xBottom, self.layout.coors[0][ndx]) - pos.x() 
    664         dY = self.transform(QwtPlot.yLeft,   self.layout.coors[1][ndx]) - pos.y() 
     665        ndx, min = self.networkCurve.closest_node(px, py) 
     666         
     667        dX = self.transform(QwtPlot.xBottom, self.networkCurve.coors[ndx][0]) - pos.x() 
     668        dY = self.transform(QwtPlot.yLeft,   self.networkCurve.coors[ndx][1]) - pos.y() 
    665669        # transform to pixel distance 
    666670        distance = math.sqrt(dX**2 + dY**2) 
    667         if ndx != -1 and distance <= self.vertices[ndx].size / 2: 
     671        if ndx != -1 and distance <= self.networkCurve.vertices[ndx].size: 
    668672            if not self.appendToSelection and not self.controlPressed: 
    669673                self.removeSelection() 
    670674                       
    671675            if self.insideview: 
    672                 self.networkCurve.unSelect() 
    673                 self.vertices[ndx].selected = not self.vertices[ndx].selected 
     676                self.networkCurve.unselect() 
     677                self.networkCurve.vertices[ndx].selected = not self.networkCurve.vertices[ndx].selected 
    674678                self.optimize(100) 
    675679                 
    676680                self.markSelectionNeighbours() 
    677681            else: 
    678                 self.vertices[ndx].selected = not self.vertices[ndx].selected 
     682                self.networkCurve.vertices[ndx].selected = not self.networkCurve.vertices[ndx].selected 
    679683                self.markSelectionNeighbours() 
    680684             
     
    683687            return False 
    684688            self.removeSelection() 
    685             self.unMark() 
     689            self.unmark() 
    686690     
    687691    def updateData(self): 
     
    721725    #          edges = [(ind / matrix.dim, ind % matrix.dim) for v, ind in vals] 
    722726    #          print "number of component edges:", len(edges), "number of components:", len(components) 
    723             components_c = [(sum(self.layout.coors[0][c]) / len(c), sum(self.layout.coors[1][c]) / len(c)) for c in components] 
     727            components_c = [(sum(self.networkCurve.coors[c][0]) / len(c), sum(self.networkCurve.coors[c][1]) / len(c)) for c in components] 
    724728            weights = [1 - matrix[u,v] for u,v in edges] 
    725729             
     
    744748         
    745749        if self.insideview == 1: 
    746             selection = self.networkCurve.getSelectedVertices() 
     750            selection = self.networkCurve.get_selected_nodes() 
    747751            if len(selection) >= 1: 
    748752                visible = set() 
    749753                visible |= set(selection) 
    750754                visible |= self.getNeighboursUpTo(selection[0], self.insideviewNeighbours) 
    751                 self.networkCurve.setHiddenVertices(set(range(self.graph.number_of_nodes())) - visible) 
     755                self.networkCurve.set_hidden_nodes(set(range(self.graph.number_of_nodes())) - visible) 
    752756     
    753757        edgesCount = 0 
     
    783787        if len(vertices) > 0: 
    784788            for vertex in vertices: 
    785                 x1 = float(self.layout.coors[0][vertex]) 
    786                 y1 = float(self.layout.coors[1][vertex]) 
     789                x1 = float(self.networkCurve.coors[vertex][0]) 
     790                y1 = float(self.networkCurve.coors[vertex][1]) 
    787791                 
    788792                if vertex in self.markerKeys: 
     
    813817            return 
    814818         
    815         if self.layout is None or self.graph is None or self.graph.items() is None: 
     819        if self.layout is None or self.graph is None or self.items is None: 
    816820            return 
    817821         
    818         if str(self.showComponentAttribute) not in self.graph.items().domain: 
     822        if str(self.showComponentAttribute) not in self.items.domain: 
    819823            self.showComponentAttribute = None 
    820824            return 
     
    826830                continue 
    827831             
    828             vertices = [vertex for vertex in component if self.vertices[vertex].show] 
     832            vertices = [vertex for vertex in component if self.networkCurve.vertices[vertex].show] 
    829833     
    830834            if len(vertices) == 0: 
    831835                continue 
    832836             
    833             xes = [self.layout.coors[0][vertex] for vertex in vertices]   
    834             yes = [self.layout.coors[1][vertex] for vertex in vertices]   
     837            xes = [self.networkCurve.coors[vertex][0] for vertex in vertices]   
     838            yes = [self.networkCurve.coors[vertex][1] for vertex in vertices]   
    835839                                   
    836840            x1 = sum(xes) / len(xes) 
    837841            y1 = sum(yes) / len(yes) 
    838842             
    839             lbl = str(self.graph.items()[component[0]][str(self.showComponentAttribute)]) 
     843            lbl = str(self.items[component[0]][str(self.showComponentAttribute)]) 
    840844             
    841845            mkey = self.addMarker(lbl, float(x1), float(y1), alignment=Qt.AlignCenter, size=self.fontSize) 
     
    847851      self.tips.removeAll() 
    848852      if len(self.tooltipText) > 0: 
    849         for vertex in self.vertices: 
     853        for vertex in self.networkCurve.vertices.itervalues(): 
    850854          if not vertex.show: 
    851855            continue 
    852856           
    853           x1 = self.layout.coors[0][vertex.index] 
    854           y1 = self.layout.coors[1][vertex.index] 
     857          x1 = self.networkCurve.coors[vertex.index][0] 
     858          y1 = self.networkCurve.coors[vertex.index][1] 
    855859          lbl = "" 
    856           values = self.graph.items()[vertex.index] 
     860          values = self.items[vertex.index] 
    857861          for ndx in self.tooltipText: 
    858               if not ndx in self.graph.items().domain: 
     862              if not ndx in self.items.domain: 
    859863                  continue 
    860864               
     
    875879    def drawLabels(self): 
    876880        if len(self.labelText) > 0: 
    877             for vertex in self.vertices: 
     881            for vertex in self.networkCurve.vertices.itervalues(): 
    878882                if not vertex.show: 
    879883                    continue 
     
    882886                    continue 
    883887                                   
    884                 x1 = self.layout.coors[0][vertex.index] 
    885                 y1 = self.layout.coors[1][vertex.index] 
     888                x1 = self.networkCurve.coors[vertex.index][0] 
     889                y1 = self.networkCurve.coors[vertex.index][1] 
    886890                lbl = "" 
    887                 values = self.graph.items()[vertex.index] 
     891                values = self.items[vertex.index] 
    888892                if self.showMissingValues: 
    889893                    lbl = ", ".join([str(values[ndx]) for ndx in self.labelText]) 
     
    900904    def drawIndexes(self): 
    901905        if self.showIndexes: 
    902             for vertex in self.vertices: 
     906            for vertex in self.networkCurve.vertices.itervalues(): 
    903907                if not vertex.show: 
    904908                    continue 
     
    907911                    continue 
    908912                                   
    909                 x1 = self.layout.coors[0][vertex.index] 
    910                 y1 = self.layout.coors[1][vertex.index] 
     913                x1 = self.networkCurve.coors[vertex.index][0] 
     914                y1 = self.networkCurve.coors[vertex.index][1] 
    911915     
    912916                lbl = str(vertex.index) 
     
    923927                    continue 
    924928                                   
    925                 x1 = (self.layout.coors[0][edge.u.index] + self.layout.coors[0][edge.v.index]) / 2 
    926                 y1 = (self.layout.coors[1][edge.u.index] + self.layout.coors[1][edge.v.index]) / 2 
     929                x1 = (self.networkCurve.coors[edge.u.index][0] + self.networkCurve.coors[edge.v.index][0]) / 2 
     930                y1 = (self.networkCurve.coors[edge.u.index][1] + self.networkCurve.coors[edge.v.index][1]) / 2 
    927931                 
    928932                if edge.weight == None: 
     
    965969        return colorIndices, colorIndex, minValue, maxValue 
    966970     
    967     def setEdgeColor(self, attribute): 
     971    def set_edge_color(self, attribute): 
    968972        if self.graph is None: 
    969973            return 
    970974         
    971         colorIndices, colorIndex, minValue, maxValue = self.getColorIndeces(self.graph.links(), attribute, self.discEdgePalette) 
     975        colorIndices, colorIndex, minValue, maxValue = self.getColorIndeces(self.links, attribute, self.discEdgePalette) 
    972976     
    973977        for index in range(len(self.networkCurve.edges)): 
     
    977981                    continue 
    978982                 
    979                 if self.graph.links().domain[colorIndex].varType == orange.VarTypes.Continuous: 
     983                if self.links.domain[colorIndex].varType == orange.VarTypes.Continuous: 
    980984                    newColor = self.discEdgePalette[0] 
    981                     if str(self.graph.links()[links_index][colorIndex]) != "?": 
     985                    if str(self.links[links_index][colorIndex]) != "?": 
    982986                        if maxValue == minValue: 
    983987                            newColor = self.discEdgePalette[0] 
    984988                        else: 
    985                             value = (float(self.graph.links()[links_index][colorIndex].value) - minValue) / (maxValue - minValue) 
     989                            value = (float(self.links[links_index][colorIndex].value) - minValue) / (maxValue - minValue) 
    986990                            newColor = self.contEdgePalette[value] 
    987991                         
    988                     self.networkCurve.setEdgeColor(index, newColor) 
     992                    self.networkCurve.set_edge_color(index, newColor) 
    989993                     
    990                 elif self.graph.links().domain[colorIndex].varType == orange.VarTypes.Discrete: 
    991                     newColor = self.discEdgePalette[colorIndices[self.graph.links()[links_index][colorIndex].value]] 
    992                     if self.graph.links()[links_index][colorIndex].value == "0": 
    993                       self.networkCurve.setEdgeColor(index, newColor, nocolor=1) 
     994                elif self.links.domain[colorIndex].varType == orange.VarTypes.Discrete: 
     995                    newColor = self.discEdgePalette[colorIndices[self.links[links_index][colorIndex].value]] 
     996                    if self.links[links_index][colorIndex].value == "0": 
     997                      self.networkCurve.set_edge_color(index, newColor, nocolor=1) 
    994998                    else: 
    995                       self.networkCurve.setEdgeColor(index, newColor) 
     999                      self.networkCurve.set_edge_color(index, newColor) 
    9961000                     
    9971001            else: 
    9981002                newColor = self.discEdgePalette[0] 
    999                 self.networkCurve.setEdgeColor(index, newColor) 
     1003                self.networkCurve.set_edge_color(index, newColor) 
    10001004         
    10011005        self.replot() 
    10021006     
    1003     def setVertexColor(self, attribute): 
     1007    def set_node_color(self, attribute, nodes=None): 
    10041008        if self.graph is None: 
    10051009            return 
    10061010         
    1007         colorIndices, colorIndex, minValue, maxValue = self.getColorIndeces(self.graph.items(), attribute, self.discPalette) 
    1008      
    1009         for v in range(self.graph.number_of_nodes()): 
    1010             if colorIndex != None:     
    1011                 if self.graph.items().domain[colorIndex].varType == orange.VarTypes.Continuous: 
    1012                     newColor = self.discPalette[0] 
     1011        if nodes is None: 
     1012            nodes = self.networkCurve.vertices.itervalues() 
     1013        else: 
     1014            nodes = (self.networkCurve.vertices[nodes] for node in nodes)  
     1015             
     1016        colorIndices, colorIndex, minValue, maxValue = self.getColorIndeces(self.items, attribute, self.discPalette) 
     1017     
     1018        if colorIndex is not None and self.items.domain[colorIndex].varType == orange.VarTypes.Continuous: 
     1019            for vertex in nodes: 
     1020                v = vertex.index 
     1021                newColor = self.discPalette[0] 
     1022                 
     1023                if str(self.items[v][colorIndex]) != "?": 
     1024                    if maxValue == minValue: 
     1025                        newColor = self.discPalette[0] 
     1026                    else: 
     1027                        value = (float(self.items[v][colorIndex].value) - minValue) / (maxValue - minValue) 
     1028                        newColor = self.contPalette[value] 
    10131029                     
    1014                     if str(self.graph.items()[v][colorIndex]) != "?": 
    1015                         if maxValue == minValue: 
    1016                             newColor = self.discPalette[0] 
    1017                         else: 
    1018                             value = (float(self.graph.items()[v][colorIndex].value) - minValue) / (maxValue - minValue) 
    1019                             newColor = self.contPalette[value] 
    1020                          
    1021                     self.networkCurve.setVertexColor(v, newColor) 
    1022                      
    1023                 elif self.graph.items().domain[colorIndex].varType == orange.VarTypes.Discrete: 
    1024                     newColor = self.discPalette[colorIndices[self.graph.items()[v][colorIndex].value]] 
    1025                     #print newColor 
    1026                     self.networkCurve.setVertexColor(v, newColor) 
    1027                      
    1028             else: 
    1029                 newColor = self.discPalette[0] 
    1030                 self.networkCurve.setVertexColor(v, newColor) 
    1031          
     1030                self.networkCurve.set_node_color(v, newColor) 
     1031                 
     1032        elif colorIndex is not None and self.items.domain[colorIndex].varType == orange.VarTypes.Discrete: 
     1033            for vertex in nodes: 
     1034                v = vertex.index 
     1035                newColor = self.discPalette[colorIndices[self.items[v][colorIndex].value]] 
     1036                self.networkCurve.set_node_color(v, newColor) 
     1037        else: 
     1038            self.networkCurve.set_nodes_color(nodes, self.discPalette[0]) 
     1039             
    10321040        self.replot() 
    10331041         
    10341042    def setLabelText(self, attributes): 
    10351043        self.labelText = [] 
    1036         if self.layout is None or self.graph is None or self.graph.items() is None: 
     1044        if self.layout is None or self.graph is None or self.items is None: 
    10371045            return 
    10381046         
    1039         if isinstance(self.graph.items(), orange.ExampleTable): 
    1040             data = self.graph.items() 
     1047        if isinstance(self.items, orange.ExampleTable): 
     1048            data = self.items 
    10411049            for att in attributes: 
    10421050                for i in range(len(data.domain)): 
     
    10441052                        self.labelText.append(i) 
    10451053                         
    1046                 if self.graph.items().domain.hasmeta(att): 
    1047                         self.labelText.append(self.graph.items().domain.metaid(att)) 
     1054                if self.items.domain.hasmeta(att): 
     1055                        self.labelText.append(self.items.domain.metaid(att)) 
    10481056     
    10491057    def setTooltipText(self, attributes): 
    10501058        self.tooltipText = [] 
    1051         if self.layout is None or self.graph is None or self.graph.items() is None: 
     1059        if self.layout is None or self.graph is None or self.items is None: 
    10521060            return 
    10531061         
    1054         if isinstance(self.graph.items(), orange.ExampleTable): 
    1055             data = self.graph.items() 
     1062        if isinstance(self.items, orange.ExampleTable): 
     1063            data = self.items 
    10561064            for att in attributes: 
    10571065                for i in range(len(data.domain)): 
     
    10591067                        self.tooltipText.append(i) 
    10601068                         
    1061                 if self.graph.items().domain.hasmeta(att): 
    1062                         self.tooltipText.append(self.graph.items().domain.metaid(att)) 
     1069                if self.items.domain.hasmeta(att): 
     1070                        self.tooltipText.append(self.items.domain.metaid(att)) 
    10631071                         
    10641072    def setEdgeLabelText(self, attributes): 
    10651073        self.edgeLabelText = [] 
    1066         if self.layout is None or self.graph is None or self.graph.items() is None: 
     1074        if self.layout is None or self.graph is None or self.items is None: 
    10671075            return 
    10681076         
    1069     def set_graph_layout(self, graph, layout, curve=None): 
     1077    def change_graph(self, newgraph, inter_nodes, add_nodes, remove_nodes): 
     1078        self.graph = newgraph 
     1079         
     1080        [self.networkCurve.vertices.pop(key) for key in remove_nodes] 
     1081        self.networkCurve.vertices.update(dict((v, NodeItem(v)) for v in add_nodes)) 
     1082        vertices = self.networkCurve.vertices 
     1083         
     1084        #build edge index 
     1085        row_ind = {} 
     1086        if self.links is not None and len(self.links) > 0: 
     1087          for i, r in enumerate(self.links): 
     1088              u = int(r['u'].value) 
     1089              v = int(r['v'].value) 
     1090              if u in self.graph and v in self.graph: 
     1091                  u_dict = row_ind.get(u, {}) 
     1092                  v_dict = row_ind.get(v, {}) 
     1093                  u_dict[v] = i 
     1094                  v_dict[u] = i 
     1095                  row_ind[u] = u_dict 
     1096                  row_ind[v] = v_dict 
     1097                   
     1098        #add edges 
     1099        if self.links is not None and len(self.links) > 0: 
     1100            links = self.links 
     1101            links_indices = (row_ind[i + 1][j + 1] for (i, j) in self.graph.edges()) 
     1102            labels = ([str(row[r].value) for r in range(2, len(row))] for row in (links[links_index] for links_index in links_indices)) 
     1103             
     1104            if self.graph.is_directed(): 
     1105                edges = [EdgeItem(vertices[i], vertices[j], 
     1106                    self.graph[i][j].get('weight', 1), 0, 1, links_index, label) for \ 
     1107                    ((i, j), links_index, label) in zip(self.graph.edges(), \ 
     1108                                                        links_indices, labels)] 
     1109            else: 
     1110                edges = [EdgeItem(vertices[i], vertices[j], 
     1111                    self.graph[i][j].get('weight', 1), links_index, label) for \ 
     1112                    ((i, j), links_index, label) in zip(self.graph.edges(), \ 
     1113                                                        links_indices, labels)] 
     1114        elif self.graph.is_directed(): 
     1115            edges = [EdgeItem(vertices[i], vertices[j], 
     1116                                      self.graph[i][j].get('weight', 1), 0, 1) for (i, j) in self.graph.edges()] 
     1117        else: 
     1118            edges = [EdgeItem(vertices[i], vertices[j], 
     1119                                      self.graph[i][j].get('weight', 1)) for (i, j) in self.graph.edges()] 
     1120                   
     1121        #self.minEdgeWeight = min(edge.weight for edge in edges) if len(edges) > 0 else 0 
     1122        #self.maxEdgeWeight = max(edge.weight for edge in edges) if len(edges) > 0 else 0 
     1123         
     1124        #if self.minEdgeWeight is None:  
     1125        #    self.minEdgeWeight = 0  
     1126         
     1127        #if self.maxEdgeWeight is None:  
     1128        #    self.maxEdgeWeight = 0  
     1129                           
     1130        #self.maxEdgeSize = 10 
     1131             
     1132        #self.setEdgesSize() 
     1133        #self.setVerticesSize() 
     1134         
     1135        self.networkCurve.coors = self.layout.map_to_graph(self.graph) 
     1136        self.networkCurve.edges = edges 
     1137        self.networkCurve.changed() 
     1138         
     1139    def set_graph_layout(self, graph, layout, curve=None, items=None, links=None): 
    10701140        self.clear() 
    10711141        self.vertexDegree = [] 
    1072         self.vertices_old = {} 
    1073         self.vertices = [] 
    1074         self.edges_old = {} 
    1075         self.edges = [] 
     1142        #self.vertices_old = {} 
     1143        #self.vertices = [] 
     1144        #self.edges_old = {} 
     1145        #self.edges = [] 
    10761146        self.minEdgeWeight = sys.maxint 
    10771147        self.maxEdgeWeight = 0 
     
    10811151            self.layout = None 
    10821152            self.networkCurve = None 
     1153            self.items = None 
     1154            self.links = None 
    10831155            xMin = self.axisScaleDiv(QwtPlot.xBottom).interval().minValue() 
    10841156            xMax = self.axisScaleDiv(QwtPlot.xBottom).interval().maxValue() 
     
    10931165        self.layout = layout 
    10941166        self.networkCurve = NetworkCurve(self) if curve is None else curve 
     1167        self.items = items if items is not None else self.graph.items() 
     1168        self.links = links if links is not None else self.graph.links() 
    10951169         
    10961170        #add nodes 
    1097         self.vertices_old = [(None, []) for v in self.graph] 
    1098         self.vertices = [NetworkVertex(v) for v in self.graph] 
     1171        #self.vertices_old = [(None, []) for v in self.graph] 
     1172        vertices = dict((v, NodeItem(v)) for v in self.graph) 
    10991173         
    11001174        #build edge index 
    11011175        row_ind = {} 
    1102         if self.graph.links() is not None and len(self.graph.links()) > 0: 
    1103           for i, r in enumerate(self.graph.links()): 
     1176        if self.links is not None and len(self.links) > 0: 
     1177          for i, r in enumerate(self.links): 
    11041178              u = int(r['u'].value) 
    11051179              v = int(r['v'].value) 
    1106               u_dict = row_ind.get(u, {}) 
    1107               v_dict = row_ind.get(v, {}) 
    1108               u_dict[v] = i 
    1109               v_dict[u] = i 
    1110               row_ind[u] = u_dict 
    1111               row_ind[v] = v_dict 
     1180              if u in self.graph and v in self.graph: 
     1181                  u_dict = row_ind.get(u, {}) 
     1182                  v_dict = row_ind.get(v, {}) 
     1183                  u_dict[v] = i 
     1184                  v_dict[u] = i 
     1185                  row_ind[u] = u_dict 
     1186                  row_ind[v] = v_dict 
    11121187               
    11131188        #add edges 
    1114         if self.graph.links() is not None and len(self.graph.links()) > 0: 
    1115             links = self.graph.links() 
     1189        if self.links is not None and len(self.links) > 0: 
     1190            links = self.links 
    11161191            links_indices = (row_ind[i + 1][j + 1] for (i, j) in self.graph.edges()) 
    11171192            labels = ([str(row[r].value) for r in range(2, len(row))] for row in (links[links_index] for links_index in links_indices)) 
    11181193             
    11191194            if self.graph.is_directed(): 
    1120                 self.edges = [NetworkEdge(self.vertices[i], self.vertices[j], 
     1195                edges = [EdgeItem(vertices[i], vertices[j], 
    11211196                    graph[i][j].get('weight', 1), 0, 1, links_index, label) for \ 
    11221197                    ((i, j), links_index, label) in zip(self.graph.edges(), \ 
    11231198                                                        links_indices, labels)] 
    11241199            else: 
    1125                 self.edges = [NetworkEdge(self.vertices[i], self.vertices[j], 
     1200                edges = [EdgeItem(vertices[i], vertices[j], 
    11261201                    graph[i][j].get('weight', 1), links_index, label) for \ 
    11271202                    ((i, j), links_index, label) in zip(self.graph.edges(), \ 
    11281203                                                        links_indices, labels)] 
    11291204        elif self.graph.is_directed(): 
    1130             self.edges = [NetworkEdge(self.vertices[i], self.vertices[j], 
     1205            edges = [EdgeItem(vertices[i], vertices[j], 
    11311206                                      graph[i][j].get('weight', 1), 0, 1) for (i, j) in self.graph.edges()] 
    11321207        else: 
    1133             self.edges = [NetworkEdge(self.vertices[i], self.vertices[j],  
     1208            edges = [EdgeItem(vertices[i], vertices[j], 
    11341209                                      graph[i][j].get('weight', 1)) for (i, j) in self.graph.edges()] 
    11351210         
    1136         self.minEdgeWeight = min(edge.weight for edge in self.edges) if len(self.edges) > 0 else 0 
    1137         self.maxEdgeWeight = max(edge.weight for edge in self.edges) if len(self.edges) > 0 else 0 
     1211        self.minEdgeWeight = min(edge.weight for edge in edges) if len(edges) > 0 else 0 
     1212        self.maxEdgeWeight = max(edge.weight for edge in edges) if len(edges) > 0 else 0 
    11381213         
    11391214        if self.minEdgeWeight is None:  
     
    11481223        self.setVerticesSize() 
    11491224         
    1150         self.networkCurve.coors = self.layout.coors 
    1151         self.networkCurve.vertices = self.vertices 
    1152         self.networkCurve.edges = self.edges 
     1225        self.networkCurve.coors = self.layout.map_to_graph(self.graph) 
     1226        self.networkCurve.vertices = vertices 
     1227        self.networkCurve.edges = edges 
    11531228        self.networkCurve.changed() 
    11541229         
     
    11591234            #print 'minEdgeWeight',self.minEdgeWeight 
    11601235            k = (self.maxEdgeSize - 1) / (self.maxEdgeWeight - self.minEdgeWeight) 
    1161             for edge in self.edges: 
     1236            for edge in self.networkCurve.edges: 
    11621237                if edge.weight == None: 
    11631238                    size = 1 
     
    11721247                    edge.pen.setCapStyle(Qt.RoundCap) 
    11731248        else: 
    1174             for edge in self.edges: 
     1249            for edge in self.networkCurve.edges: 
    11751250                edge.pen = QPen(edge.pen.color(), 1) 
    11761251                edge.pen.setCapStyle(Qt.RoundCap) 
    11771252                 
    11781253    def setVerticesSize(self, column=None, inverted=0): 
    1179         if self.layout is None or self.graph is None or self.graph.items() is None: 
     1254        if self.layout is None or self.graph is None or self.items is None: 
    11801255            return 
    11811256         
    11821257        column = str(column) 
    11831258         
    1184         if column in self.graph.items().domain or (column.startswith("num of ") and column.replace("num of ", "") in self.graph.items().domain): 
     1259        if column in self.items.domain or (column.startswith("num of ") and column.replace("num of ", "") in self.items.domain): 
    11851260            values = [] 
    11861261             
    1187             if column in self.graph.items().domain: 
    1188                 values = [x[column].value for x in self.graph.items() if not x[column].isSpecial()] 
     1262            if column in self.items.domain: 
     1263                values = [self.items[x][column].value for x in self.graph if not self.items[x][column].isSpecial()] 
    11891264            else: 
    1190                 values = [len(x[column.replace("num of ", "")].value.split(',')) for x in self.graph.items()] 
     1265                values = [len(self.items[x][column.replace("num of ", "")].value.split(',')) for x in self.graph] 
    11911266           
    11921267            minVertexWeight = float(min(values or [0])) 
     
    12051280                  
    12061281            if inverted: 
    1207                 for vertex in self.vertices: 
    1208                     if column in self.graph.items().domain: 
    1209                         vertex.size = self.maxVertexSize - ((getValue(self.graph.items()[vertex.index][column]) - minVertexWeight) * k) 
     1282                for key, vertex in self.networkCurve.vertices.iteritems(): 
     1283                    if column in self.items.domain: 
     1284                        vertex.size = self.maxVertexSize - ((getValue(self.items[vertex.index][column]) - minVertexWeight) * k) 
    12101285                    else: 
    1211                         vertex.size = self.maxVertexSize - ((len(self.graph.items()[vertex.index][column.replace("num of ", "")].value.split(',')) - minVertexWeight) * k) 
     1286                        vertex.size = self.maxVertexSize - ((len(self.items[vertex.index][column.replace("num of ", "")].value.split(',')) - minVertexWeight) * k) 
    12121287                     
    12131288                     
    12141289                    vertex.pen.setWidthF(1 + float(vertex.size) / 20) 
    12151290            else: 
    1216                 for vertex in self.vertices: 
    1217                     if column in self.graph.items().domain: 
    1218                         vertex.size = (getValue(self.graph.items()[vertex.index][column]) - minVertexWeight) * k + self.minVertexSize 
     1291                for key, vertex in self.networkCurve.vertices.iteritems(): 
     1292                    if column in self.items.domain: 
     1293                        vertex.size = (getValue(self.items[vertex.index][column]) - minVertexWeight) * k + self.minVertexSize 
    12191294                    else: 
    1220                         vertex.size = (float(len(self.graph.items()[vertex.index][column.replace("num of ", "")].value.split(','))) - minVertexWeight) * k + self.minVertexSize 
     1295                        vertex.size = (float(len(self.items[vertex.index][column.replace("num of ", "")].value.split(','))) - minVertexWeight) * k + self.minVertexSize 
    12211296                         
    12221297                    #print vertex.size 
    12231298                    vertex.pen.setWidthF(1 + float(vertex.size) / 20) 
    12241299        else: 
    1225             for vertex in self.vertices: 
     1300            for key, vertex in self.networkCurve.vertices.iteritems(): 
    12261301                vertex.size = self.maxVertexSize 
    12271302                vertex.pen.setWidthF(1 + float(vertex.size) / 20) 
     
    12391314         
    12401315    def zoomSelection(self): 
    1241         selection = self.networkCurve.getSelectedVertices() 
     1316        selection = self.networkCurve.get_selected_nodes() 
    12421317        if len(selection) > 0:  
    1243             x = [self.layout.coors[0][v] for v in selection] 
    1244             y = [self.layout.coors[1][v] for v in selection] 
     1318            x = [self.networkCurve.coors[v][0] for v in selection] 
     1319            y = [self.networkCurve.coors[v][1] for v in selection] 
    12451320     
    12461321            oldXMin = self.axisScaleDiv(QwtPlot.xBottom).interval().minValue() 
  • orange/OrangeWidgets/Unsupervised/OWNxClustering.py

    r8042 r8156  
    11""" 
    2 <name>Nx Clustering</name> 
     2<name>Net Clustering</name> 
    33<description>Orange widget for community detection in networks</description> 
    44<icon>icons/Network.png</icon> 
    55<contact>Miha Stajdohar (miha.stajdohar(@at@)gmail.com)</contact>  
    6 <priority>6440</priority> 
     6<priority>6430</priority> 
    77""" 
    88 
  • orange/OrangeWidgets/Unsupervised/OWNxExplorer.py

    r9450 r9483  
    11""" 
    2 <name>Nx Explorer</name> 
     2<name>Net Explorer</name> 
    33<description>Orange widget for network exploration.</description> 
    44<icon>icons/Network.png</icon> 
    55<contact>Miha Stajdohar (miha.stajdohar(@at@)gmail.com)</contact>  
    6 <priority>6430</priority> 
     6<priority>6420</priority> 
    77""" 
    88import math 
     
    4545        OWWidget.__init__(self, parent, signalManager, name) 
    4646        #self.contextHandlers = {"": DomainContextHandler("", [ContextField("attributes", selected="markerAttributes"), ContextField("attributes", selected="tooltipAttributes"), "color"])} 
    47         self.inputs = [("Network", Orange.network.Graph, self.set_graph, Default),  
     47        self.inputs = [("Network", Orange.network.Graph, self.set_graph, Default), 
     48                       ("Nx View", Orange.network.NxView, self.set_network_view), 
    4849                       ("Items", Orange.data.Table, self.setItems), 
    4950                       ("Items to Mark", Orange.data.Table, self.markItems),  
     
    118119        self.loadSettings() 
    119120         
     121        self._network_view = None 
    120122        self.layout = Orange.network.GraphLayout() 
    121123        self.graph = None 
     124        self.graph_base = None 
    122125        self.markInputItems = None 
    123126         
     
    172175        self.vertexSizeCombo.addItem("(none)") 
    173176         
    174         OWGUI.spin(self.vertexSizeCombo.box, self, "minVertexSize", 5, 200, 1, label="Min vertex size:", callback = self.setVertexSize) 
    175         OWGUI.spin(self.vertexSizeCombo.box, self, "maxVertexSize", 5, 200, 1, label="Max vertex size:", callback = self.setVertexSize) 
     177        OWGUI.spin(self.vertexSizeCombo.box, self, "minVertexSize", 5, 200, 1, label="Min vertex size:", callback=self.setVertexSize) 
     178        OWGUI.spin(self.vertexSizeCombo.box, self, "maxVertexSize", 5, 200, 1, label="Max vertex size:", callback=self.setVertexSize) 
    176179        OWGUI.checkBox(self.vertexSizeCombo.box, self, "invertSize", "Invert vertex size", callback = self.setVertexSize) 
    177180         
     
    376379     
    377380    def setAutoSendAttributes(self): 
    378         if self.autoSendAttributes: 
    379             self.networkCanvas.callbackSelectVertex = self.sendAttSelectionList 
    380         else: 
    381             self.networkCanvas.callbackSelectVertex = None 
     381        print 'TODO setAutoSendAttributes' 
     382        #if self.autoSendAttributes: 
     383        #    self.networkCanvas.callbackSelectVertex = self.sendAttSelectionList 
     384        #else: 
     385        #    self.networkCanvas.callbackSelectVertex = None 
    382386 
    383387    def sendAttSelectionList(self): 
    384388        if not self.graph is None: 
    385             vars = [x.name for x in self.graph.items_vars()] 
     389            vars = [x.name for x in self.graph_base.links_vars()] 
    386390            if not self.comboAttSelection.currentText() in vars: 
    387391                return 
    388392            att = str(self.comboAttSelection.currentText()) 
    389             vertices = self.networkCanvas.networkCurve.getSelectedVertices() 
     393            vertices = self.networkCanvas.networkCurve.get_selected_vertices() 
    390394             
    391395            if len(vertices) != 1: 
    392396                return 
    393397             
    394             attributes = str(self.graph.items()[vertices[0]][att]).split(', ') 
     398            attributes = str(self.graph_base.items()[vertices[0]][att]).split(', ') 
    395399        else: 
    396400            attributes = None 
     
    401405            return 
    402406         
    403         vars = [x.name for x in self.graph.items_vars()] 
     407        vars = [x.name for x in self.graph_base.items_vars()] 
    404408        if not self.editCombo.currentText() in vars: 
    405409            return 
    406410        att = str(self.editCombo.currentText()) 
    407         vertices = self.networkCanvas.networkCurve.getSelectedVertices() 
     411        vertices = self.networkCanvas.networkCurve.get_selected_vertices() 
    408412         
    409413        if len(vertices) == 0: 
    410414            return 
    411415         
    412         if self.graph.items().domain[att].var_type == Orange.data.Type.Continuous: 
     416        if self.graph_base.items().domain[att].var_type == Orange.data.Type.Continuous: 
    413417            for v in vertices: 
    414                 self.graph.items()[v][att] = float(self.editValue) 
     418                self.graph_base.items()[v][att] = float(self.editValue) 
    415419