source: orange/Orange/data/preprocess/scaling.py @ 10913:1b281e538a8f

Revision 10913:1b281e538a8f, 82.2 KB checked in by mstajdohar, 22 months ago (diff)

Fixed Radviz jittering. Before, points in the center were scattered all around the plot.

Line 
1"""
2.. index:: data scaling
3
4.. index::
5   single: scaling
6
7**************************
8Data Scaling (``scaling``)
9**************************
10
11This module is a conglomerate of Orange 2.0 modules orngScaleData,
12orngScaleLinProjData, orngScaleLinProjData3D, orngScalePolyvizData and orngScaleScatterPlotData. The
13documentation is poor and has to be improved in the future.
14
15.. autoclass:: Orange.data.preprocess.scaling.ScaleData
16   :members:
17   :show-inheritance:
18
19.. autoclass:: Orange.data.preprocess.scaling.ScaleLinProjData
20   :members:
21   :show-inheritance:
22
23.. autoclass:: Orange.data.preprocess.scaling.ScaleLinProjData3D
24   :members:
25   :show-inheritance:
26
27.. autoclass:: Orange.data.preprocess.scaling.ScalePolyvizData
28   :members:
29   :show-inheritance:
30
31.. autoclass:: Orange.data.preprocess.scaling.ScaleScatterPlotData
32   :members:
33   :show-inheritance:
34
35.. autofunction:: get_variable_values_sorted
36
37.. autofunction:: get_variable_value_indices
38
39.. autofunction:: discretize_domain
40
41"""
42
43
44import sys
45import numpy
46import random
47import time
48try:
49    import numpy.ma as MA
50except:
51    import numpy.core.ma as MA
52from copy import copy
53from math import sqrt
54import math
55
56import Orange
57import Orange.core
58import Orange.data
59from Orange.data import preprocess
60
61from Orange.utils import caching
62
63import warnings
64
65from Orange.utils import deprecated_keywords, deprecated_members
66
67def get_variable_values_sorted(variable):
68    """
69    Return a list of sorted values for given attribute.
70   
71    EXPLANATION: if variable values have values 1, 2, 3, 4, ... then their
72    order in orange depends on when they appear first in the data. With this
73    function we get a sorted list of values.
74   
75    """
76    if variable.var_type == Orange.core.VarTypes.Continuous:
77        print "get_variable_values_sorted - attribute %s is a continuous variable" % variable
78        return []
79
80    values = list(variable.values)
81    int_values = []
82
83    # do all attribute values containt integers?
84    try:
85        int_values = [(int(val), val) for val in values]
86    except ValueError:
87        return values
88
89    # if all values were intergers, we first sort them ascendently
90    int_values.sort()
91    return [val[1] for val in int_values]
92
93@deprecated_keywords({"sortValuesForDiscreteAttrs":
94                      "sort_values_for_discrete_attrs"})
95def get_variable_value_indices(variable, sort_values_for_discrete_attrs=1):
96    """
97    Create a dictionary with given variable. Keys are variable values, values
98    are indices (transformed from string to int); in case all values are
99    integers, we also sort them.
100   
101    """
102    if variable.var_type == Orange.core.VarTypes.Continuous:
103        print "get_variable_value_indices - attribute %s is a continuous "\
104              "variable" % (str(variable))
105        return {}
106
107    if sort_values_for_discrete_attrs:
108        values = get_variable_values_sorted(variable)
109    else:
110        values = list(variable.values)
111    return dict([(values[i], i) for i in range(len(values))])
112
113
114@deprecated_keywords({"removeUnusedValues": "remove_unused_values",
115                      "numberOfIntervals": "number_of_intervals"})
116def discretize_domain(data, remove_unused_values = 1, number_of_intervals = 2):
117    """
118    Discretize the domain. If we have a class, remove the instances with missing
119    class value, discretize the continuous class into discrete class with two
120    values, discretize continuous attributes using entropy discretization (or
121    equiN if we don't have a class or class is continuous).
122    """
123    entro_disc = preprocess.EntropyDiscretization()
124    equi_disc  = preprocess.EquiNDiscretization(number_of_intervals=number_of_intervals)
125    disc_attrs = []
126
127    classname = (data and len(data) > 0 and data.domain.class_var and
128                 data.domain.class_var.name or None)
129
130    if not data or len(data) == 0:
131        return None
132
133    # if we have a continuous class we have to discretize it before we can
134    # discretize the attributes
135    if classname and data.domain.class_var.var_type == \
136                     Orange.core.VarTypes.Continuous:
137        try:
138            newclass = equi_disc(data.domain.class_var.name, data)
139            newclass.name = classname
140        except Orange.core.KernelException, ex:
141            warnings.warn("Could not discretize class variable '%s'. %s" %
142                          (data.domain.class_var.name, ex.message))
143            newclass = None
144            classname = None
145        new_domain = Orange.data.Domain(data.domain.attributes, newclass)
146        data = Orange.data.Table(new_domain, data)
147
148    for attr in data.domain.attributes:
149        try:
150            name = attr.name
151            if attr.var_type == Orange.core.VarTypes.Continuous:
152                # if continuous attribute then use entropy discretization
153                if data.domain.class_var and data.domain.class_var.var_type == \
154                   Orange.core.VarTypes.Discrete:
155                    new_attr = entro_disc(attr, data)
156                else:
157                    new_attr = equi_disc(attr, data)
158            else:
159                new_attr = attr
160            if remove_unused_values:
161                new_attr = preprocess.RemoveUnusedValues(new_attr, data)
162                if new_attr is None:
163                    raise Orange.core.KernelException, "No values"
164           
165            new_attr.name = name
166            disc_attrs.append(new_attr)
167        except Orange.core.KernelException, ex:
168            # if all values are missing, entropy discretization will throw an
169            # exception. in such cases ignore the attribute
170            warnings.warn("Could not discretize %s attribute. %s" %
171                          (attr.name, ex.message))
172
173    if classname: disc_attrs.append(data.domain.class_var)
174    d2 = data.translate(disc_attrs, True)
175    return d2
176
177
178class ScaleData:
179    def __init__(self):
180        self.raw_data = None           # input data
181        self.raw_subset_data = None
182        self.attribute_names = []    # list of attribute names from self.raw_data
183        self.attribute_name_index = {}  # dict with indices to attributes
184        self.attribute_flip_info = {}   # dictionary with attrName: 0/1 attribute is flipped or not
185       
186        self.data_has_class = False
187        self.data_has_continuous_class = False
188        self.data_has_discrete_class = False
189        self.data_class_name = None
190        self.data_domain = None
191        self.data_class_index = None
192        self.have_data = False
193        self.have_subset_data = False
194
195        self.jitter_size = 10
196        self.jitter_continuous = 0
197        self.jitter_seed = 0
198
199        self.attr_values = {}
200        self.domain_data_stat = []
201        self.original_data = self.original_subset_data = None    # input (nonscaled) data in a numpy array
202        self.scaled_data = self.scaled_subset_data = None        # scaled data to the interval 0-1
203        self.no_jittering_scaled_data = self.no_jittering_scaled_subset_data = None
204        self.valid_data_array = self.valid_subset_data_array = None
205
206    @deprecated_keywords({"subsetData": "subset_data"})
207    def merge_data_sets(self, data, subset_data):
208        """
209        Take examples from data and subset_data and merge them into one
210        dataset.
211       
212        """
213        if data == None and subset_data == None: None
214        if subset_data == None:
215            full_data = data
216        elif data == None:
217            full_data = subset_data
218        else:
219            full_data = Orange.data.Table(data)
220            full_data.extend(subset_data)
221        return full_data
222   
223    mergeDataSets = merge_data_sets
224
225    def rescale_data(self):
226        """
227        Force the existing data to be rescaled due to changes like
228        jitter_continuous, jitter_size, ...
229        """
230        self.set_data(self.raw_data, self.raw_subset_data, skipIfSame = 0)
231   
232    rescaleData = rescale_data
233
234    @deprecated_keywords({"subsetData": "subset_data",
235                          "sortValuesForDiscreteAttrs":
236                          "sort_values_for_discrete_attrs"})
237    def set_data(self, data, subset_data = None, **args):
238        if args.get("skipIfSame", 1):
239            if (((data == None and self.raw_data == None) or
240                (self.raw_data != None and data != None and
241                 self.raw_data.checksum() == data.checksum())) and
242                ((subset_data == None and self.raw_subset_data == None) or
243                 (self.raw_subset_data != None and subset_data != None and
244                  self.raw_subset_data.checksum() == subset_data.checksum()))):
245                    return
246
247        self.domain_data_stat = []
248        self.attr_values = {}
249        self.original_data = self.original_subset_data = None
250        self.scaled_data = self.scaled_subset_data = None
251        self.no_jittering_scaled_data = self.no_jittering_scaled_subset_data = None
252        self.valid_data_array = self.valid_subset_data_array = None
253
254        self.raw_data = None
255        self.raw_subset_data = None
256        self.have_data = False
257        self.have_subset_data = False
258        self.data_has_class = False
259        self.data_has_continuous_class = False
260        self.data_has_discrete_class = False
261        self.data_class_name = None
262        self.data_domain = None
263        self.data_class_index = None
264               
265        if data == None: return
266        full_data = self.merge_data_sets(data, subset_data)
267               
268        self.raw_data = data
269        self.raw_subset_data = subset_data
270
271        len_data = data and len(data) or 0
272
273        self.attribute_names = [attr.name for attr in full_data.domain]
274        self.attribute_name_index = dict([(full_data.domain[i].name, i)
275                                          for i in range(len(full_data.domain))])
276        self.attribute_flip_info = {}         # dict([(attr.name, 0) for attr in full_data.domain]) # reset the fliping information
277       
278        self.data_domain = full_data.domain
279        self.data_has_class = bool(full_data.domain.class_var)
280        self.data_has_continuous_class = bool(self.data_has_class and
281                                              full_data.domain.class_var.var_type == Orange.core.VarTypes.Continuous)
282        self.data_has_discrete_class = bool(self.data_has_class and
283                                            full_data.domain.class_var.var_type == Orange.core.VarTypes.Discrete)
284        self.data_class_name = self.data_has_class and full_data.domain.class_var.name
285        if self.data_has_class:
286            self.data_class_index = self.attribute_name_index[self.data_class_name]
287        self.have_data = bool(self.raw_data and len(self.raw_data) > 0)
288        self.have_subset_data = bool(self.raw_subset_data and
289                                     len(self.raw_subset_data) > 0)
290       
291        self.domain_data_stat = caching.getCached(full_data,
292                                          Orange.core.DomainBasicAttrStat,
293                                          (full_data,))
294
295        sort_values_for_discrete_attrs = args.get("sort_values_for_discrete_attrs",
296                                                  1)
297
298        for index in range(len(full_data.domain)):
299            attr = full_data.domain[index]
300            if attr.var_type == Orange.core.VarTypes.Discrete:
301                self.attr_values[attr.name] = [0, len(attr.values)]
302            elif attr.var_type == Orange.core.VarTypes.Continuous:
303                self.attr_values[attr.name] = [self.domain_data_stat[index].min,
304                                               self.domain_data_stat[index].max]
305       
306        # the original_data, no_jittering_scaled_data and validArray are arrays
307        # that we can cache so that other visualization widgets don't need to
308        # compute it. The scaled_data on the other hand has to be computed for
309        # each widget separately because of different
310        # jitter_continuous and jitter_size values
311        if caching.getCached(data, "visualizationData") and subset_data == None:
312            self.original_data, self.no_jittering_scaled_data, self.valid_data_array = caching.getCached(data,"visualizationData")
313            self.original_subset_data = self.no_jittering_scaled_subset_data = self.valid_subset_data_array = numpy.array([]).reshape([len(self.original_data), 0])
314        else:
315            no_jittering_data = full_data.toNumpyMA("ac")[0].T
316            valid_data_array = numpy.array(1-no_jittering_data.mask,
317                                           numpy.short)  # have to convert to int array, otherwise when we do some operations on this array we get overflow
318            no_jittering_data = numpy.array(MA.filled(no_jittering_data,
319                                                      Orange.core.Illegal_Float))
320            original_data = no_jittering_data.copy()
321           
322            for index in range(len(data.domain)):
323                attr = data.domain[index]
324                if attr.var_type == Orange.core.VarTypes.Discrete:
325                    # see if the values for discrete attributes have to be resorted
326                    variable_value_indices = get_variable_value_indices(data.domain[index],
327                                                                        sort_values_for_discrete_attrs)
328                    if 0 in [i == variable_value_indices[attr.values[i]]
329                             for i in range(len(attr.values))]:
330                        # make the array a contiguous, otherwise the putmask
331                        # function does not work
332                        line = no_jittering_data[index].copy()
333                        indices = [numpy.where(line == val, 1, 0)
334                                   for val in range(len(attr.values))]
335                        for i in range(len(attr.values)):
336                            numpy.putmask(line, indices[i],
337                                          variable_value_indices[attr.values[i]])
338                        no_jittering_data[index] = line   # save the changed array
339                        original_data[index] = line     # reorder also the values in the original data
340                    no_jittering_data[index] = ((no_jittering_data[index]*2.0 + 1.0)
341                                                / float(2*len(attr.values)))
342                   
343                elif attr.var_type == Orange.core.VarTypes.Continuous:
344                    diff = self.domain_data_stat[index].max - self.domain_data_stat[index].min or 1     # if all values are the same then prevent division by zero
345                    no_jittering_data[index] = (no_jittering_data[index] -
346                                                self.domain_data_stat[index].min) / diff
347
348            self.original_data = original_data[:,:len_data]; self.original_subset_data = original_data[:,len_data:]
349            self.no_jittering_scaled_data = no_jittering_data[:,:len_data]; self.no_jittering_scaled_subset_data = no_jittering_data[:,len_data:]
350            self.valid_data_array = valid_data_array[:,:len_data]; self.valid_subset_data_array = valid_data_array[:,len_data:]
351       
352        if data: caching.setCached(data, "visualizationData",
353                           (self.original_data, self.no_jittering_scaled_data,
354                            self.valid_data_array))
355        if subset_data: caching.setCached(subset_data, "visualizationData",
356                                  (self.original_subset_data,
357                                   self.no_jittering_scaled_subset_data,
358                                   self.valid_subset_data_array))
359           
360        # compute the scaled_data arrays
361        scaled_data = numpy.concatenate([self.no_jittering_scaled_data,
362                                         self.no_jittering_scaled_subset_data],
363                                         axis = 1)
364
365        # Random generators for jittering
366        random = numpy.random.RandomState(seed=self.jitter_seed)
367        rand_seeds = random.random_integers(0, sys.maxint - 1, size=len(data.domain))
368        for index, rseed in zip(range(len(data.domain)), rand_seeds):
369            # Need to use a different seed for each feature
370            random = numpy.random.RandomState(seed=rseed)
371            attr = data.domain[index]
372            if attr.var_type == Orange.core.VarTypes.Discrete:
373                scaled_data[index] += (self.jitter_size/(50.0*max(1,len(attr.values))))*\
374                                      (random.rand(len(full_data)) - 0.5)
375               
376            elif attr.var_type == Orange.core.VarTypes.Continuous and self.jitter_continuous:
377                scaled_data[index] += self.jitter_size/50.0 * (0.5 - random.rand(len(full_data)))
378                scaled_data[index] = numpy.absolute(scaled_data[index])       # fix values below zero
379                ind = numpy.where(scaled_data[index] > 1.0, 1, 0)     # fix values above 1
380                numpy.putmask(scaled_data[index], ind, 2.0 - numpy.compress(ind, scaled_data[index]))
381
382        if self.have_subset_data:
383            # Fix all subset instances which are also in the main data
384            # to have the same jittered values
385            ids_to_indices = dict((inst.id, i) \
386                                  for i, inst in enumerate(self.raw_data))
387
388            subset_ids_map = [[i, ids_to_indices[s.id]] \
389                               for i, s in enumerate(self.raw_subset_data)\
390                               if s.id in ids_to_indices]
391            if len(subset_ids_map):
392                subset_ids_map = numpy.array(subset_ids_map)
393                subset_ids_map[:, 0] += len_data
394                scaled_data[:, subset_ids_map[:, 0]] = \
395                        scaled_data[:, subset_ids_map[:, 1]]
396
397        self.scaled_data = scaled_data[:,:len_data]; self.scaled_subset_data = scaled_data[:,len_data:]
398   
399    setData = set_data
400
401    @deprecated_keywords({"example": "instance"})
402    def scale_example_value(self, instance, index):
403        """
404        Scale instance's value at index index to a range between 0 and 1 with
405        respect to self.raw_data.
406        """
407        if instance[index].isSpecial():
408            print "Warning: scaling instance with missing value"
409            return 0.5     #1e20
410        if instance.domain[index].var_type == Orange.core.VarTypes.Discrete:
411            d = get_variable_value_indices(instance.domain[index])
412            return (d[instance[index].value]*2 + 1) / float(2*len(d))
413        elif instance.domain[index].var_type == Orange.core.VarTypes.Continuous:
414            diff = self.domain_data_stat[index].max - self.domain_data_stat[index].min
415            if diff == 0: diff = 1          # if all values are the same then prevent division by zero
416            return (instance[index] - self.domain_data_stat[index].min) / diff
417
418    scaleExampleValue = scale_example_value
419
420    @deprecated_keywords({"attrName": "attr_name"})
421    def get_attribute_label(self, attr_name):
422        if self.attribute_flip_info.get(attr_name, 0) and self.data_domain[attr_name].var_type == Orange.core.VarTypes.Continuous:
423            return "-" + attr_name
424        return attr_name
425   
426    getAttributeLabel = get_attribute_label
427
428    @deprecated_keywords({"attrName": "attr_name"})
429    def flip_attribute(self, attr_name):
430        if attr_name not in self.attribute_names: return 0
431        if self.data_domain[attr_name].var_type == Orange.core.VarTypes.Discrete: return 0
432
433        index = self.attribute_name_index[attr_name]
434        self.attribute_flip_info[attr_name] = 1 - self.attribute_flip_info.get(attr_name, 0)
435        if self.data_domain[attr_name].var_type == Orange.core.VarTypes.Continuous:
436            self.attr_values[attr_name] = [-self.attr_values[attr_name][1], -self.attr_values[attr_name][0]]
437
438        self.scaled_data[index] = 1 - self.scaled_data[index]
439        self.scaled_subset_data[index] = 1 - self.scaled_subset_data[index]
440        self.no_jittering_scaled_data[index] = 1 - self.no_jittering_scaled_data[index]
441        self.no_jittering_scaled_subset_data[index] = 1 - self.no_jittering_scaled_subset_data[index]
442        return 1
443
444    flipAttribute = flip_attribute
445   
446    def get_min_max_val(self, attr):
447        if type(attr) == int:
448            attr = self.attribute_names[attr]
449        diff = self.attr_values[attr][1] - self.attr_values[attr][0]
450        return diff or 1.0
451
452    getMinMaxVal = get_min_max_val
453
454    @deprecated_keywords({"alsoClassIfExists": "also_class_if_exists"})
455    def get_valid_list(self, indices, also_class_if_exists = 1):
456        """
457        Get array of 0 and 1 of len = len(self.raw_data). If there is a missing
458        value at any attribute in indices return 0 for that instance.
459        """
460        if self.valid_data_array == None or len(self.valid_data_array) == 0:
461            return numpy.array([], numpy.bool)
462       
463        inds = indices[:]
464        if also_class_if_exists and self.data_has_class: 
465            inds.append(self.data_class_index) 
466        selected_array = self.valid_data_array.take(inds, axis = 0)
467        arr = numpy.add.reduce(selected_array)
468        return numpy.equal(arr, len(inds))
469   
470    getValidList = get_valid_list
471
472    @deprecated_keywords({"alsoClassIfExists": "also_class_if_exists"})
473    def get_valid_subset_list(self, indices, also_class_if_exists = 1):
474        """
475        Get array of 0 and 1 of len = len(self.raw_subset_data). if there is a
476        missing value at any attribute in indices return 0 for that instance.
477        """
478        if self.valid_subset_data_array == None or len(self.valid_subset_data_array) == 0:
479            return numpy.array([], numpy.bool)
480        inds = indices[:]
481        if also_class_if_exists and self.data_class_index: 
482            inds.append(self.data_class_index)
483        selected_array = self.valid_subset_data_array.take(inds, axis = 0)
484        arr = numpy.add.reduce(selected_array)
485        return numpy.equal(arr, len(inds))
486   
487    getValidSubsetList = get_valid_subset_list
488
489    def get_valid_indices(self, indices):
490        """
491        Get array with numbers that represent the instance indices that have a
492        valid data value.
493        """
494        valid_list = self.get_valid_list(indices)
495        return numpy.nonzero(valid_list)[0]
496   
497    getValidIndices = get_valid_indices
498
499    def get_valid_subset_indices(self, indices):
500        """
501        Get array with numbers that represent the instance indices that have a
502        valid data value.
503        """
504        valid_list = self.get_valid_subset_list(indices)
505        return numpy.nonzero(valid_list)[0]
506   
507    getValidSubsetIndices = get_valid_subset_indices
508
509    def rnd_correction(self, max):
510        """
511        Return a number from -max to max.
512        """
513        return (random.random() - 0.5)*2*max
514   
515    rndCorrection = rnd_correction
516
517ScaleData = deprecated_members({"rawData": "raw_data",
518                                "rawSubsetData": "raw_subset_data",
519                                "attributeNames": "attribute_names",
520                                "attributeNameIndex": "attribute_name_index",
521                                "attributeFlipInfo": "attribute_flip_info",
522                                "dataHasClass": "data_has_class",
523                                "dataHasContinuousClass": "data_has_continuous_class",
524                                "dataHasDiscreteClass": "data_has_discrete_class",
525                                "dataClassName": "data_class_name",
526                                "dataDomain": "data_domain",
527                                "dataClassIndex": "data_class_index",
528                                "haveData": "have_data",
529                                "haveSubsetData": "have_subset_data",
530                                "jitterSize": "jitter_size",
531                                "jitterContinuous": "jitter_continuous",
532                                "attrValues": "attr_values",
533                                "domainDataStat": "domain_data_stat",
534                                "originalData": "original_data",
535                                "originalSubsetData": "original_subset_data",
536                                "scaledData": "scaled_data",
537                                "scaledSubsetData": "scaled_subset_data",
538                                "noJitteringScaledData": "no_jittering_scaled_data",
539                                "noJitteringScaledSubsetData": "no_jittering_scaled_subset_data",
540                                "validDataArray": "valid_data_array",
541                                "validSubsetDataArray": "valid_subset_data_array",
542                                "mergeDataSets": "merge_data_sets",
543                                "rescaleData": "rescale_data",
544                                "setData": "set_data",
545                                "scaleExampleValue": "scale_example_value",
546                                "getAttributeLabel": "get_attribute_label",
547                                "flipAttribute": "flip_attribute",
548                                "getMinMaxVal": "get_min_max_val",
549                                "getValidList": "get_valid_list",
550                                "getValidSubsetList": "get_valid_subset_list",
551                                "getValidIndices": "get_valid_indices",
552                                "getValidSubsetIndices": "get_valid_subset_indices",
553                                "rndCorrection": "rnd_correction",
554                                })(ScaleData)
555
556
557class ScaleLinProjData(ScaleData):
558    def __init__(self):
559        ScaleData.__init__(self)
560        self.normalize_examples = 1
561        self.anchor_data =[]        # form: [(anchor1x, anchor1y, label1),(anchor2x, anchor2y, label2), ...]
562        self.last_attr_indices = None
563        self.anchor_dict = {}
564
565    @deprecated_keywords({"xAnchors": "xanchors", "yAnchors": "yanchors"})
566    def set_anchors(self, xanchors, yanchors, attributes):
567        if attributes:
568            if xanchors != None and yanchors != None:
569                self.anchor_data = [(xanchors[i], yanchors[i], attributes[i])
570                                    for i in range(len(attributes))]
571            else:
572                self.anchor_data = self.create_anchors(len(attributes), attributes)
573   
574    setAnchors = set_anchors
575
576    @deprecated_keywords({"numOfAttr": "num_of_attr"})
577    def create_anchors(self, num_of_attr, labels = None):
578        """
579        Create anchors around the circle.
580       
581        """
582        xanchors = self.create_xanchors(num_of_attr)
583        yanchors = self.create_yanchors(num_of_attr)
584        if labels:
585            return [(xanchors[i], yanchors[i], labels[i]) for i in range(num_of_attr)]
586        else:
587            return [(xanchors[i], yanchors[i]) for i in range(num_of_attr)]
588   
589    createAnchors = create_anchors
590
591    @deprecated_keywords({"numOfAttrs": "num_of_attrs"})
592    def create_xanchors(self, num_of_attrs):
593        if not self.anchor_dict.has_key(num_of_attrs):
594            self.anchor_dict[num_of_attrs] = (numpy.cos(numpy.arange(num_of_attrs)
595                                                        * 2*math.pi
596                                                        / float(num_of_attrs)),
597                                              numpy.sin(numpy.arange(num_of_attrs)
598                                                        * 2*math.pi
599                                                        / float(num_of_attrs)))
600        return self.anchor_dict[num_of_attrs][0]
601   
602    createXAnchors = create_xanchors
603
604    @deprecated_keywords({"numOfAttrs": "num_of_attrs"})
605    def create_yanchors(self, num_of_attrs):
606        if not self.anchor_dict.has_key(num_of_attrs):
607            self.anchor_dict[num_of_attrs] = (numpy.cos(numpy.arange(num_of_attrs)
608                                                        * 2*math.pi
609                                                        / float(num_of_attrs)),
610                                              numpy.sin(numpy.arange(num_of_attrs)
611                                                        * 2*math.pi
612                                                        / float(num_of_attrs)))
613        return self.anchor_dict[num_of_attrs][1]
614
615    createYAnchors = create_yanchors
616
617    @deprecated_keywords({"fileName": "filename", "attrList": "attrlist",
618                          "useAnchorData": "use_anchor_data"})
619    def save_projection_as_tab_data(self, filename, attrlist, use_anchor_data = 0):
620        """
621        Save projection (xattr, yattr, classval) into a filename filename.
622       
623        """
624        Orange.core.saveTabDelimited(filename,
625            self.create_projection_as_example_table([self.attribute_name_index[i]
626                                                     for i in attrlist],
627                                                    use_anchor_data = use_anchor_data))
628   
629    saveProjectionAsTabData = save_projection_as_tab_data
630
631    @deprecated_keywords({"attrIndices": "attr_indices",
632                          "settingsDict": "settings_dict",
633                          "useAnchorData": "use_anchor_data",
634                          "xAnchors": "xanchors",
635                          "yAnchors": "yanchors",
636                          "anchorRadius": "anchor_radius",
637                          "normalizeExample": "normalize_example"
638                          })
639    def get_projected_point_position(self, attr_indices, values, **settings_dict):
640        """
641        For attributes in attr_indices and values of these attributes in values
642        compute point positions. This function has more sense in radviz and
643        polyviz methods.
644   
645        """
646        # load the elements from the settings dict
647        use_anchor_data = settings_dict.get("use_anchor_data")
648        xanchors = settings_dict.get("x_anchors")
649        yanchors = settings_dict.get("y_anchors")
650        anchor_radius = settings_dict.get("anchor_radius")
651        normalize_example = settings_dict.get("normalize_example")
652
653        if attr_indices != self.last_attr_indices:
654            print "get_projected_point_position. Warning: Possible bug. The "+\
655                  "set of attributes is not the same as when computing the "+\
656                  "whole projection"
657
658        if xanchors != None and yanchors != None:
659            xanchors = numpy.array(xanchors)
660            yanchors = numpy.array(yanchors)
661            if anchor_radius == None: anchor_radius = numpy.sqrt(xanchors*xanchors +
662                                                                 yanchors*yanchors)
663        elif use_anchor_data and self.anchor_data:
664            xanchors = numpy.array([val[0] for val in self.anchor_data])
665            yanchors = numpy.array([val[1] for val in self.anchor_data])
666            if anchor_radius == None: anchor_radius = numpy.sqrt(xanchors*xanchors +
667                                                                 yanchors*yanchors)
668        else:
669            xanchors = self.create_xanchors(len(attr_indices))
670            yanchors = self.create_yanchors(len(attr_indices))
671            anchor_radius = numpy.ones(len(attr_indices), numpy.float)
672
673        if normalize_example == 1 or (normalize_example == None
674                                      and self.normalize_examples):
675            m = min(values); M = max(values)
676            if m < 0.0 or M > 1.0: 
677                # we have to do rescaling of values so that all the values will
678                # be in the 0-1 interval
679                #print "example values are not in the 0-1 interval"
680                values = [max(0.0, min(val, 1.0)) for val in values]
681                #m = min(m, 0.0); M = max(M, 1.0); diff = max(M-m, 1e-10)
682                #values = [(val-m) / float(diff) for val in values]
683
684            s = sum(numpy.array(values)*anchor_radius)
685            if s == 0: return [0.0, 0.0]
686            x = self.trueScaleFactor * numpy.dot(xanchors*anchor_radius,
687                                                 values) / float(s)
688            y = self.trueScaleFactor * numpy.dot(yanchors*anchor_radius,
689                                                 values) / float(s)
690        else:
691            x = self.trueScaleFactor * numpy.dot(xanchors, values)
692            y = self.trueScaleFactor * numpy.dot(yanchors, values)
693
694        return [x, y]
695   
696    getProjectedPointPosition = get_projected_point_position
697
698    @deprecated_keywords({"attrIndices": "attr_indices",
699                          "settingsDict": "settings_dict"})
700    def create_projection_as_example_table(self, attr_indices, **settings_dict):
701        """
702        Create the projection of attribute indices given in attr_indices and
703        create an example table with it.
704        """
705        if self.data_domain.class_var:
706            domain = settings_dict.get("domain") or \
707                     Orange.data.Domain([Orange.feature.Continuous("xVar"),
708                                         Orange.feature.Continuous("yVar"),
709                                         Orange.feature.Discrete(self.data_domain.class_var.name,
710                                                                       values = get_variable_values_sorted(self.data_domain.class_var))])
711        else:
712            domain = settings_dict.get("domain") or \
713                     Orange.data.Domain([Orange.feature.Continuous("xVar"),
714                                         Orange.feature.Continuous("yVar")])
715        data = self.create_projection_as_numeric_array(attr_indices,
716                                                       **settings_dict)
717        if data != None:
718            return Orange.data.Table(domain, data)
719        else:
720            return Orange.data.Table(domain)
721
722    createProjectionAsExampleTable = create_projection_as_example_table
723
724    @deprecated_keywords({"attrIndices": "attr_indices",
725                          "settingsDict": "settings_dict",
726                          "validData": "valid_data",
727                          "classList": "class_list",
728                          "XAnchors": "xanchors",
729                          "YAnchors": "yanchors",
730                          "scaleFactor": "scale_factor",
731                          "jitterSize": "jitter_size",
732                          "useAnchorData": "use_anchor_data",
733                          "removeMissingData": "remove_missing_data",
734                          "useSubsetData": "use_subset_data",
735                          })
736    def create_projection_as_numeric_array(self, attr_indices, **settings_dict):
737        # load the elements from the settings dict
738        valid_data = settings_dict.get("valid_data")
739        class_list = settings_dict.get("class_list")
740        sum_i     = settings_dict.get("sum_i")
741        xanchors = settings_dict.get("xanchors")
742        yanchors = settings_dict.get("yanchors")
743        scale_factor = settings_dict.get("scale_factor", 1.0)
744        normalize = settings_dict.get("normalize")
745        jitter_size = settings_dict.get("jitter_size", 0.0)
746        use_anchor_data = settings_dict.get("use_anchor_data", 0)
747        remove_missing_data = settings_dict.get("remove_missing_data", 1)
748        use_subset_data = settings_dict.get("use_subset_data", 0)        # use the data or subsetData?
749        #minmaxVals = settings_dict.get("minmaxVals", None)
750
751        # if we want to use anchor data we can get attr_indices from the anchor_data
752        if use_anchor_data and self.anchor_data:
753            attr_indices = [self.attribute_name_index[val[2]] for val in self.anchor_data]
754
755        if valid_data == None:
756            if use_subset_data: valid_data = self.get_valid_subset_list(attr_indices)
757            else:             valid_data = self.get_valid_list(attr_indices)
758        if sum(valid_data) == 0:
759            return None
760
761        if class_list == None and self.data_domain.class_var:
762            if use_subset_data: class_list = self.original_subset_data[self.data_class_index]
763            else:             class_list = self.original_data[self.data_class_index]
764
765        # if jitterSize is set below zero we use scaled_data that has already jittered data
766        if use_subset_data:
767            if jitter_size < 0.0: data = self.scaled_subset_data
768            else:                data = self.no_jittering_scaled_subset_data
769        else:
770            if jitter_size < 0.0: data = self.scaled_data
771            else:                data = self.no_jittering_scaled_data
772
773        selectedData = numpy.take(data, attr_indices, axis = 0)
774        if remove_missing_data:
775            selectedData = numpy.compress(valid_data, selectedData, axis = 1)
776            if class_list != None and len(class_list) != numpy.shape(selectedData)[1]:
777                class_list = numpy.compress(valid_data, class_list)
778
779        if use_anchor_data and self.anchor_data:
780            xanchors = numpy.array([val[0] for val in self.anchor_data])
781            yanchors = numpy.array([val[1] for val in self.anchor_data])
782            r = numpy.sqrt(xanchors*xanchors + yanchors*yanchors)     # compute the distance of each anchor from the center of the circle
783            if normalize == 1 or (normalize == None and self.normalize_examples):
784                xanchors *= r
785                yanchors *= r
786        elif (xanchors != None and yanchors != None):
787            xanchors = numpy.array(xanchors); yanchors = numpy.array(yanchors)
788            r = numpy.sqrt(xanchors*xanchors + yanchors*yanchors)     # compute the distance of each anchor from the center of the circle
789        else:
790            xanchors = self.create_xanchors(len(attr_indices))
791            yanchors = self.create_yanchors(len(attr_indices))
792            r = numpy.ones(len(xanchors), numpy.float)
793
794        x_positions = numpy.dot(xanchors, selectedData)
795        y_positions = numpy.dot(yanchors, selectedData)
796
797        if normalize == 1 or (normalize == None and self.normalize_examples):
798            if sum_i == None:
799                sum_i = self._getSum_i(selectedData, use_anchor_data, r)
800            x_positions /= sum_i
801            y_positions /= sum_i
802            self.trueScaleFactor = scale_factor
803        else:
804            if not remove_missing_data:
805                try:
806                    x_valid_data = numpy.compress(valid_data, x_positions)
807                    y_valid_data = numpy.compress(valid_data, y_positions)
808                except:
809                    print valid_data
810                    print x_positions
811                    print numpy.shape(valid_data)
812                    print numpy.shape(x_positions)
813            else:
814                x_valid_data = x_positions
815                y_valid_data = y_positions
816           
817            dist = math.sqrt(max(x_valid_data*x_valid_data + y_valid_data*y_valid_data)) or 1
818            self.trueScaleFactor = scale_factor / dist
819
820        self.unscaled_x_positions = numpy.array(x_positions)
821        self.unscaled_y_positions = numpy.array(y_positions)
822
823        if self.trueScaleFactor != 1.0:
824            x_positions *= self.trueScaleFactor
825            y_positions *= self.trueScaleFactor
826
827        if jitter_size > 0.0:
828            x_positions += numpy.random.uniform(-jitter_size, jitter_size, len(x_positions))
829            y_positions += numpy.random.uniform(-jitter_size, jitter_size, len(y_positions))
830
831        self.last_attr_indices = attr_indices
832        if class_list != None:
833            return numpy.transpose(numpy.array((x_positions, y_positions, class_list)))
834        else:
835            return numpy.transpose(numpy.array((x_positions, y_positions)))
836
837    createProjectionAsNumericArray = create_projection_as_numeric_array
838   
839    @deprecated_keywords({"useAnchorData": "use_anchor_data",
840                          "anchorRadius": "anchor_radius"})
841    def _getsum_i(self, data, use_anchor_data = 0, anchor_radius = None):
842        """
843        Function to compute the sum of all values for each element in the data.
844        Used to normalize.
845       
846        """
847        if use_anchor_data:
848            if anchor_radius == None:
849                anchor_radius = numpy.sqrt([a[0]**2+a[1]**2 for a in self.anchor_data])
850            sum_i = numpy.add.reduce(numpy.transpose(numpy.transpose(data)*anchor_radius))
851        else:
852            sum_i = numpy.add.reduce(data)
853        if len(sum_i[numpy.nonzero(sum_i)]) < len(sum_i):    # test if there are zeros in sum_i
854            sum_i += numpy.where(sum_i == 0, 1.0, 0.0)
855        return sum_i
856   
857    _getSum_i = _getsum_i
858
859graph_deprecator = deprecated_members({"setData": "set_data",
860                                       "updateData": "update_data",
861                                       "scaleFactor": "scale_factor"})
862
863ScaleLinProjData = deprecated_members({"setAnchors": "set_anchors",
864                                       "createAnchors": "create_anchors",
865                                       "createXAnchors": "create_xanchors",
866                                       "createYAnchors": "create_yanchors",
867                                       "saveProjectionAsTabData": "save_projection_as_tab_data",
868                                       "getProjectedPointPosition":
869                                           "get_projected_point_position",
870                                       "createProjectionAsExampleTable":
871                                           "create_projection_as_example_table",
872                                       "createProjectionAsNumericArray":
873                                           "create_projection_as_numeric_array",
874                                       "_getSum_i": "_getsum_i",
875                                       "normalizeExamples": "normalize_examples",
876                                       "anchorData": "anchor_data",
877                                       "lastAttrIndices": "last_attr_indices",
878                                       "anchorDict": "anchor_dict"})(ScaleLinProjData)
879
880class ScaleLinProjData3D(ScaleData):
881    def __init__(self):
882        ScaleData.__init__(self)
883        self.normalize_examples = 1
884        self.anchor_data = []        # form: [(anchor1x, anchor1y, anchor1z, label1),(anchor2x, anchor2y, anchor2z, label2), ...]
885        self.last_attr_indices = None
886        self.anchor_dict = {}
887
888    @deprecated_keywords({"xAnchors": "xanchors", "yAnchors": "yanchors"})
889    def set_anchors(self, xanchors, yanchors, zanchors, attributes):
890        if attributes:
891            if xanchors != None and yanchors != None and zanchors != None:
892                self.anchor_data = [(xanchors[i], yanchors[i], zanchors[i], attributes[i])
893                                    for i in range(len(attributes))]
894            else:
895                self.anchor_data = self.create_anchors(len(attributes), attributes)
896
897    setAnchors = set_anchors
898
899    @deprecated_keywords({"numOfAttr": "num_of_attr"})
900    def create_anchors(self, num_of_attrs, labels=None):
901        """
902        Create anchors on the sphere.
903       
904        """
905        # Golden Section Spiral algorithm approximates even distribution of points on a sphere
906        # (read more here http://www.softimageblog.com/archives/115)
907        n = num_of_attrs
908        xanchors = []
909        yanchors = []
910        zanchors = []
911
912        inc = math.pi * (3 - math.sqrt(5))
913        off = 2. / n
914        for k in range(n):
915            y = k * off - 1 + (off / 2)
916            r = math.sqrt(1 - y*y)
917            phi = k * inc
918            xanchors.append(math.cos(phi)*r)
919            yanchors.append(y)
920            zanchors.append(math.sin(phi)*r)
921
922        self.anchor_dict[num_of_attrs] = [xanchors, yanchors, zanchors]
923 
924        if labels:
925            return [(xanchors[i], yanchors[i], zanchors[i], labels[i]) for i in range(num_of_attrs)]
926        else:
927            return [(xanchors[i], yanchors[i], zanchors[i]) for i in range(num_of_attrs)]
928
929    createAnchors = create_anchors
930
931    @deprecated_keywords({"numOfAttrs": "num_of_attrs"})
932    def create_xanchors(self, num_of_attrs):
933        if not self.anchor_dict.has_key(num_of_attrs):
934            self.create_anchors(num_of_attrs)
935        return self.anchor_dict[num_of_attrs][0]
936
937    createXAnchors = create_xanchors
938
939    @deprecated_keywords({"numOfAttrs": "num_of_attrs"})
940    def create_yanchors(self, num_of_attrs):
941        if not self.anchor_dict.has_key(num_of_attrs):
942            self.create_anchors(num_of_attrs)
943        return self.anchor_dict[num_of_attrs][1]
944
945    createYAnchors = create_yanchors
946
947    @deprecated_keywords({"numOfAttrs": "num_of_attrs"})
948    def create_zanchors(self, num_of_attrs):
949        if not self.anchor_dict.has_key(num_of_attrs):
950            self.create_anchors(num_of_attrs)
951        return self.anchor_dict[num_of_attrs][2]
952
953    createZAnchors = create_zanchors
954
955    @deprecated_keywords({"fileName": "filename", "attrList": "attrlist",
956                          "useAnchorData": "use_anchor_data"})
957    def save_projection_as_tab_data(self, filename, attrlist, use_anchor_data=0):
958        """
959        Save projection (xattr, yattr, zattr, classval) into a filename filename.
960       
961        """
962        Orange.core.saveTabDelimited(filename,
963            self.create_projection_as_example_table([self.attribute_name_index[i]
964                                                     for i in attrlist],
965                                                    use_anchor_data=use_anchor_data))
966   
967    saveProjectionAsTabData = save_projection_as_tab_data
968
969    @deprecated_keywords({"attrIndices": "attr_indices",
970                          "settingsDict": "settings_dict",
971                          "useAnchorData": "use_anchor_data",
972                          "xAnchors": "xanchors",
973                          "yAnchors": "yanchors",
974                          "zAnchors": "zanchors",
975                          "anchorRadius": "anchor_radius",
976                          "normalizeExample": "normalize_example",
977                          })
978    def get_projected_point_position(self, attr_indices, values, **settings_dict):
979        """
980        For attributes in attr_indices and values of these attributes in values
981        compute point positions. This function has more sense in radviz and
982        polyviz methods.
983   
984        """
985        # load the elements from the settings dict
986        use_anchor_data = settings_dict.get("use_anchor_data")
987        xanchors = settings_dict.get('xanchors')
988        yanchors = settings_dict.get('yanchors')
989        zanchors = settings_dict.get('zanchors')
990        anchor_radius = settings_dict.get("anchor_radius")
991        normalize_example = settings_dict.get("normalize_example")
992
993        if attr_indices != self.last_attr_indices:
994            print "get_projected_point_position. Warning: Possible bug. The "+\
995                  "set of attributes is not the same as when computing the "+\
996                  "whole projection"
997
998        if xanchors != None and yanchors != None and zanchors != None:
999            xanchors = numpy.array(xanchors)
1000            yanchors = numpy.array(yanchors)
1001            zanchors = numpy.array(zanchors)
1002            if anchor_radius == None: anchor_radius = numpy.sqrt(xanchors*xanchors +
1003                                                                 yanchors*yanchors +
1004                                                                 zanchors*zanchors)
1005        elif use_anchor_data and self.anchor_data:
1006            xanchors = numpy.array([val[0] for val in self.anchor_data])
1007            yanchors = numpy.array([val[1] for val in self.anchor_data])
1008            zanchors = numpy.array([val[2] for val in self.anchor_data])
1009            if anchor_radius == None: anchor_radius = numpy.sqrt(xanchors*xanchors +
1010                                                                 yanchors*yanchors +
1011                                                                 zanchors*zanchors)
1012        else:
1013            self.create_anchors(len(attr_indices))
1014            xanchors = numpy.array([val[0] for val in self.anchor_data])
1015            yanchors = numpy.array([val[1] for val in self.anchor_data])
1016            zanchors = numpy.array([val[2] for val in self.anchor_data])
1017            anchor_radius = numpy.ones(len(attr_indices), numpy.float)
1018
1019        if normalize_example == 1 or (normalize_example == None
1020                                      and self.normalize_examples):
1021            m = min(values); M = max(values)
1022            if m < 0.0 or M > 1.0: 
1023                # we have to do rescaling of values so that all the values will
1024                # be in the 0-1 interval
1025                #print "example values are not in the 0-1 interval"
1026                values = [max(0.0, min(val, 1.0)) for val in values]
1027                #m = min(m, 0.0); M = max(M, 1.0); diff = max(M-m, 1e-10)
1028                #values = [(val-m) / float(diff) for val in values]
1029
1030            s = sum(numpy.array(values)*anchor_radius)
1031            if s == 0: return [0.0, 0.0]
1032            x = self.true_scale_factor * numpy.dot(xanchors*anchor_radius,
1033                                                 values) / float(s)
1034            y = self.true_scale_factor * numpy.dot(yanchors*anchor_radius,
1035                                                 values) / float(s)
1036            z = self.true_scale_factor * numpy.dot(zanchors*anchor_radius,
1037                                                 values) / float(s)
1038        else:
1039            x = self.true_scale_factor * numpy.dot(xanchors, values)
1040            y = self.true_scale_factor * numpy.dot(yanchors, values)
1041            z = self.true_scale_factor * numpy.dot(zanchors, values)
1042
1043        return [x, y, z]
1044
1045    getProjectedPointPosition = get_projected_point_position
1046
1047    @deprecated_keywords({"attrIndices": "attr_indices",
1048                          "settingsDict": "settings_dict"})
1049    def create_projection_as_example_table(self, attr_indices, **settings_dict):
1050        """
1051        Create the projection of attribute indices given in attr_indices and
1052        create an example table with it.
1053        """
1054        if self.data_domain.class_var:
1055            domain = settings_dict.get("domain") or \
1056                     Orange.data.Domain([Orange.feature.Continuous("xVar"),
1057                                         Orange.feature.Continuous("yVar"),
1058                                         Orange.feature.Continuous("zVar"),
1059                                         Orange.feature.Discrete(self.data_domain.class_var.name,
1060                                                                       values=get_variable_values_sorted(self.data_domain.class_var))])
1061        else:
1062            domain = settings_dict.get("domain") or \
1063                     Orange.data.Domain([Orange.feature.Continuous("xVar"),
1064                                         Orange.feature.Continuous("yVar"),
1065                                         Orange.feature.Continuous("zVar")])
1066        data = self.create_projection_as_numeric_array(attr_indices,
1067                                                       **settings_dict)
1068        if data != None:
1069            return Orange.data.Table(domain, data)
1070        else:
1071            return Orange.data.Table(domain)
1072
1073    createProjectionAsExampleTable = create_projection_as_example_table
1074
1075    @deprecated_keywords({"attrIndices": "attr_indices",
1076                          "settingsDict": "settings_dict",
1077                          "validData": "valid_data",
1078                          "classList": "class_list",
1079                          "XAnchors": "xanchors",
1080                          "YAnchors": "yanchors",
1081                          "ZAnchors": "zanchors",
1082                          "scaleFactor": "scale_factor",
1083                          "jitterSize": "jitter_size",
1084                          "useAnchorData": "use_anchor_data",
1085                          "removeMissingData": "remove_missing_data",
1086                          "useSubsetData": "use_subset_data",
1087                          })
1088    def create_projection_as_numeric_array(self, attr_indices, **settings_dict):
1089        # load the elements from the settings dict
1090        valid_data = settings_dict.get("valid_data")
1091        class_list = settings_dict.get("class_list")
1092        sum_i     = settings_dict.get("sum_i")
1093        xanchors = settings_dict.get("xanchors")
1094        yanchors = settings_dict.get("yanchors")
1095        zanchors = settings_dict.get("zanchors")
1096        scale_factor = settings_dict.get("scale_factor", 1.0)
1097        normalize = settings_dict.get("normalize")
1098        jitter_size = settings_dict.get("jitter_size", 0.0)
1099        use_anchor_data = settings_dict.get("use_anchor_data", 0)
1100        remove_missing_data = settings_dict.get("remove_missing_data", 1)
1101        use_subset_data = settings_dict.get("use_subset_data", 0)        # use the data or subsetData?
1102        #minmaxVals = settings_dict.get("minmaxVals", None)
1103
1104        # if we want to use anchor data we can get attr_indices from the anchor_data
1105        if use_anchor_data and self.anchor_data:
1106            attr_indices = [self.attribute_name_index[val[3]] for val in self.anchor_data]
1107
1108        if valid_data == None:
1109            if use_subset_data: valid_data = self.get_valid_subset_list(attr_indices)
1110            else:             valid_data = self.get_valid_list(attr_indices)
1111        if sum(valid_data) == 0:
1112            return None
1113
1114        if class_list == None and self.data_domain.class_var:
1115            if use_subset_data: class_list = self.original_subset_data[self.data_class_index]
1116            else:             class_list = self.original_data[self.data_class_index]
1117
1118        # if jitterSize is set below zero we use scaled_data that has already jittered data
1119        if use_subset_data:
1120            if jitter_size < 0.0: data = self.scaled_subset_data
1121            else:                data = self.no_jittering_scaled_subset_data
1122        else:
1123            if jitter_size < 0.0: data = self.scaled_data
1124            else:                data = self.no_jittering_scaled_data
1125
1126        selected_data = numpy.take(data, attr_indices, axis=0)
1127        if remove_missing_data:
1128            selected_data = numpy.compress(valid_data, selected_data, axis=1)
1129            if class_list != None and len(class_list) != numpy.shape(selected_data)[1]:
1130                class_list = numpy.compress(valid_data, class_list)
1131
1132        if use_anchor_data and self.anchor_data:
1133            xanchors = numpy.array([val[0] for val in self.anchor_data])
1134            yanchors = numpy.array([val[1] for val in self.anchor_data])
1135            zanchors = numpy.array([val[2] for val in self.anchor_data])
1136            r = numpy.sqrt(xanchors*xanchors + yanchors*yanchors + zanchors*zanchors)     # compute the distance of each anchor from the center of the circle
1137            if normalize == 1 or (normalize == None and self.normalize_examples):
1138                xanchors *= r
1139                yanchors *= r
1140                zanchors *= r
1141        elif (xanchors != None and yanchors != None and zanchors != None):
1142            xanchors = numpy.array(xanchors)
1143            yanchors = numpy.array(yanchors)
1144            zanchors = numpy.array(zanchors)
1145            r = numpy.sqrt(xanchors*xanchors + yanchors*yanchors + zanchors*zanchors)     # compute the distance of each anchor from the center of the circle
1146        else:
1147            self.create_anchors(len(attr_indices))
1148            xanchors = numpy.array([val[0] for val in self.anchor_data])
1149            yanchors = numpy.array([val[1] for val in self.anchor_data])
1150            zanchors = numpy.array([val[2] for val in self.anchor_data])
1151            r = numpy.ones(len(xanchors), numpy.float)
1152
1153        x_positions = numpy.dot(xanchors, selected_data)
1154        y_positions = numpy.dot(yanchors, selected_data)
1155        z_positions = numpy.dot(zanchors, selected_data)
1156
1157        if normalize == 1 or (normalize == None and self.normalize_examples):
1158            if sum_i == None:
1159                sum_i = self._getSum_i(selected_data, use_anchor_data, r)
1160            x_positions /= sum_i
1161            y_positions /= sum_i
1162            z_positions /= sum_i
1163            self.true_scale_factor = scale_factor
1164        else:
1165            if not remove_missing_data:
1166                try:
1167                    x_valid_data = numpy.compress(valid_data, x_positions)
1168                    y_valid_data = numpy.compress(valid_data, y_positions)
1169                    z_valid_data = numpy.compress(valid_data, z_positions)
1170                except:
1171                    print valid_data
1172                    print x_positions
1173                    print numpy.shape(valid_data)
1174                    print numpy.shape(x_positions)
1175            else:
1176                x_valid_data = x_positions
1177                y_valid_data = y_positions
1178                z_valid_data = z_positions
1179
1180            dist = math.sqrt(max(x_valid_data*x_valid_data + y_valid_data*y_valid_data + z_valid_data*z_valid_data)) or 1
1181            self.true_scale_factor = scale_factor / dist
1182
1183        self.unscaled_x_positions = numpy.array(x_positions)
1184        self.unscaled_y_positions = numpy.array(y_positions)
1185        self.unscaled_z_positions = numpy.array(z_positions)
1186
1187        if self.true_scale_factor != 1.0:
1188            x_positions *= self.true_scale_factor
1189            y_positions *= self.true_scale_factor
1190            z_positions *= self.true_scale_factor
1191
1192        if jitter_size > 0.0:
1193            x_positions += numpy.random.uniform(-jitter_size, jitter_size, len(x_positions))
1194            y_positions += numpy.random.uniform(-jitter_size, jitter_size, len(y_positions))
1195            z_positions += numpy.random.uniform(-jitter_size, jitter_size, len(z_positions))
1196
1197        self.last_attr_indices = attr_indices
1198        if class_list != None:
1199            return numpy.transpose(numpy.array((x_positions, y_positions, z_positions, class_list)))
1200        else:
1201            return numpy.transpose(numpy.array((x_positions, y_positions, z_positions)))
1202
1203    createProjectionAsNumericArray = create_projection_as_numeric_array
1204
1205    @deprecated_keywords({"useAnchorData": "use_anchor_data",
1206                          "anchorRadius": "anchor_radius"})
1207    def _getsum_i(self, data, use_anchor_data=0, anchor_radius=None):
1208        """
1209        Function to compute the sum of all values for each element in the data.
1210        Used to normalize.
1211       
1212        """
1213        if use_anchor_data:
1214            if anchor_radius == None:
1215                anchor_radius = numpy.sqrt([a[0]**2+a[1]**2+a[2]**2 for a in self.anchor_data])
1216            sum_i = numpy.add.reduce(numpy.transpose(numpy.transpose(data)*anchor_radius))
1217        else:
1218            sum_i = numpy.add.reduce(data)
1219        if len(numpy.nonzero(sum_i)) < len(sum_i):    # test if there are zeros in sum_i
1220            sum_i += numpy.where(sum_i == 0, 1.0, 0.0)
1221        return sum_i
1222   
1223    _getSum_i = _getsum_i
1224
1225ScaleLinProjData3D = deprecated_members({"setAnchors": "set_anchors",
1226                                       "createAnchors": "create_anchors",
1227                                       "saveProjectionAsTabData": "save_projection_as_tab_data",
1228                                       "getProjectedPointPosition":
1229                                           "get_projected_point_position",
1230                                       "createProjectionAsExampleTable":
1231                                           "create_projection_as_example_table",
1232                                       "createProjectionAsNumericArray":
1233                                           "create_projection_as_numeric_array",
1234                                       "_getSum_i": "_getsum_i",
1235                                       "normalizeExamples": "normalize_examples",
1236                                       "anchorData": "anchor_data",
1237                                       "lastAttrIndices": "last_attr_indices",
1238                                       "anchorDict": "anchor_dict",
1239                                       "trueScaleFactor": "true_scale_factor"
1240                                      })(ScaleLinProjData3D)
1241
1242class ScalePolyvizData(ScaleLinProjData):
1243    def __init__(self):
1244        ScaleLinProjData.__init__(self)
1245        self.normalize_examples = 1
1246        self.anchor_data =[]        # form: [(anchor1x, anchor1y, label1),(anchor2x, anchor2y, label2), ...]
1247       
1248
1249    # attributeReverse, validData = None, classList = None, sum_i = None, XAnchors = None, YAnchors = None, domain = None, scaleFactor = 1.0, jitterSize = 0.0
1250    @deprecated_keywords({"attrIndices": "attr_indices",
1251                          "settingsDict": "settings_dict"})
1252    def create_projection_as_example_table(self, attr_list, **settings_dict):
1253        if self.data_domain.class_var:
1254            domain = settings_dict.get("domain") or \
1255                     Orange.data.Domain([Orange.feature.Continuous("xVar"),
1256                                         Orange.feature.Continuous("yVar"),
1257                                         Orange.feature.Discrete(self.data_domain.class_var.name,
1258                                                                       values = get_variable_values_sorted(self.data_domain.class_var))])
1259        else:
1260            domain = settings_dict.get("domain") or \
1261                     Orange.data.Domain([Orange.feature.Continuous("xVar"),
1262                                         Orange.feature.Continuous("yVar")])
1263        data = self.create_projection_as_numeric_array(attr_list, **settings_dict)
1264        if data != None:
1265            return Orange.data.Table(domain, data)
1266        else:
1267            return Orange.data.Table(domain)
1268   
1269    createProjectionAsExampleTable = create_projection_as_example_table
1270   
1271    @deprecated_keywords({"attrIndices": "attr_indices",
1272                          "settingsDict": "settings_dict",
1273                          "validData": "valid_data",
1274                          "classList": "class_list",
1275                          "XAnchors": "xanchors",
1276                          "YAnchors": "yanchors",
1277                          "scaleFactor": "scale_factor",
1278                          "jitterSize": "jitter_size",
1279                          "removeMissingData": "remove_missing_data",
1280                          })
1281    def create_projection_as_numeric_array(self, attr_indices, **settings_dict):
1282        # load the elements from the settings dict
1283        attribute_reverse = settings_dict.get("reverse", [0]*len(attr_indices))
1284        valid_data = settings_dict.get("valid_data")
1285        class_list = settings_dict.get("class_list")
1286        sum_i     = settings_dict.get("sum_i")
1287        xanchors  = settings_dict.get("xanchors")
1288        yanchors  = settings_dict.get("yanchors")
1289        scale_factor = settings_dict.get("scale_factor", 1.0)
1290        jitter_size  = settings_dict.get("jitter_size", 0.0)
1291        remove_missing_data = settings_dict.get("remove_missing_data", 1)
1292       
1293        if valid_data == None:
1294            valid_data = self.get_valid_list(attr_indices)
1295        if sum(valid_data) == 0:
1296            return None
1297
1298        if class_list == None and self.data_has_class:
1299            class_list = self.original_data[self.data_class_index]
1300
1301        if remove_missing_data:
1302            selected_data = numpy.compress(valid_data,
1303                                          numpy.take(self.no_jittering_scaled_data,
1304                                                     attr_indices, axis = 0),
1305                                                     axis = 1)
1306            if class_list != None and len(class_list) != numpy.shape(selected_data)[1]:
1307                class_list = numpy.compress(valid_data, class_list)
1308        else:
1309            selected_data = numpy.take(self.no_jittering_scaled_data,
1310                                      attr_indices, axis = 0)
1311       
1312        if sum_i == None:
1313            sum_i = self._getSum_i(selected_data)
1314
1315        if xanchors == None or yanchors == None:
1316            xanchors = self.create_xanchors(len(attr_indices))
1317            yanchors = self.create_yanchors(len(attr_indices))
1318
1319        xanchors = numpy.zeros(numpy.shape(selected_data), numpy.float)
1320        yanchors = numpy.zeros(numpy.shape(selected_data), numpy.float)
1321        length = len(attr_indices)
1322
1323        for i in range(length):
1324            if attribute_reverse[i]:
1325                xanchors[i] = selected_data[i] * xanchors[i] + (1-selected_data[i]) * xanchors[(i+1)%length]
1326                yanchors[i] = selected_data[i] * yanchors[i] + (1-selected_data[i]) * yanchors[(i+1)%length]
1327            else:
1328                xanchors[i] = (1-selected_data[i]) * xanchors[i] + selected_data[i] * xanchors[(i+1)%length]
1329                yanchors[i] = (1-selected_data[i]) * yanchors[i] + selected_data[i] * yanchors[(i+1)%length]
1330
1331        x_positions = numpy.sum(numpy.multiply(xanchors, selected_data), axis=0)/sum_i
1332        y_positions = numpy.sum(numpy.multiply(yanchors, selected_data), axis=0)/sum_i
1333        #x_positions = numpy.sum(numpy.transpose(xanchors* numpy.transpose(selectedData)), axis=0) / sum_i
1334        #y_positions = numpy.sum(numpy.transpose(yanchors* numpy.transpose(selectedData)), axis=0) / sum_i
1335
1336        if scale_factor != 1.0:
1337            x_positions = x_positions * scale_factor
1338            y_positions = y_positions * scale_factor
1339        if jitter_size > 0.0:
1340            x_positions += (numpy.random.random(len(x_positions))-0.5)*jitter_size
1341            y_positions += (numpy.random.random(len(y_positions))-0.5)*jitter_size
1342
1343        if class_list != None:
1344            return numpy.transpose(numpy.array((x_positions, y_positions, class_list)))
1345        else:
1346            return numpy.transpose(numpy.array((x_positions, y_positions)))
1347
1348    createProjectionAsNumericArray = create_projection_as_numeric_array
1349
1350    @deprecated_keywords({"attrIndices": "attr_indices",
1351                          "settingsDict": "settings_dict",
1352                          "useAnchorData": "use_anchor_data",
1353                          "XAnchors": "xanchors",
1354                          "YAnchors": "yanchors"})
1355    def get_projected_point_position(self, attr_indices, values, **settings_dict):
1356        # load the elements from the settings dict
1357        attribute_reverse = settings_dict.get("reverse", [0]*len(attr_indices))
1358        use_anchor_data = settings_dict.get("use_anchor_data")
1359        xanchors = settings_dict.get("xanchors")
1360        yanchors = settings_dict.get("yanchors")
1361   
1362        if xanchors != None and yanchors != None:
1363            xanchors = numpy.array(xanchors)
1364            yanchors = numpy.array(yanchors)
1365        elif use_anchor_data:
1366            xanchors = numpy.array([val[0] for val in self.anchor_data])
1367            yanchors = numpy.array([val[1] for val in self.anchor_data])
1368        else:
1369            xanchors = self.create_xanchors(len(attr_indices))
1370            yanchors = self.create_yanchors(len(attr_indices))
1371
1372        m = min(values); M = max(values)
1373        if m < 0.0 or M > 1.0:  # we have to do rescaling of values so that all
1374            # the values will be in the 0-1 interval
1375            values = [max(0.0, min(val, 1.0)) for val in values]
1376            #m = min(m, 0.0); M = max(M, 1.0); diff = max(M-m, 1e-10)
1377            #values = [(val-m) / float(diff) for val in values]
1378       
1379        s = sum(numpy.array(values))
1380        if s == 0: return [0.0, 0.0]
1381
1382        length = len(values)
1383        xanchors = numpy.zeros(length, numpy.float)
1384        yanchors = numpy.zeros(length, numpy.float)
1385        for i in range(length):
1386            if attribute_reverse[i]:
1387                xanchors[i] = values[i] * xanchors[i] + (1-values[i]) * xanchors[(i+1)%length]
1388                yanchors[i] = values[i] * yanchors[i] + (1-values[i]) * yanchors[(i+1)%length]
1389            else:
1390                xanchors[i] = (1-values[i]) * xanchors[i] + values[i] * xanchors[(i+1)%length]
1391                yanchors[i] = (1-values[i]) * yanchors[i] + values[i] * yanchors[(i+1)%length]
1392
1393        x_positions = numpy.sum(numpy.dot(xanchors, values), axis=0) / float(s)
1394        y_positions = numpy.sum(numpy.dot(yanchors, values), axis=0) / float(s)
1395        return [x, y]
1396   
1397    getProjectedPointPosition = get_projected_point_position
1398
1399ScalePolyvizData = deprecated_members({"createProjectionAsExampleTable":
1400                                           "create_projection_as_example_table",
1401                                       "createProjectionAsNumericArray":
1402                                           "create_projection_as_numeric_array",
1403                                       "getProjectedPointPosition":
1404                                           "get_projected_point_position"
1405                                       })(ScalePolyvizData)
1406
1407class ScaleScatterPlotData(ScaleData):
1408    def get_original_data(self, indices):
1409        data = self.original_data.take(indices, axis = 0)
1410        for i, ind in enumerate(indices):
1411            [minVal, maxVal] = self.attr_values[self.data_domain[ind].name]
1412            if self.data_domain[ind].varType == Orange.core.VarTypes.Discrete:
1413                data[i] += (self.jitter_size/50.0)*(numpy.random.random(len(self.raw_data)) - 0.5)
1414            elif self.data_domain[ind].varType == Orange.core.VarTypes.Continuous and self.jitter_continuous:
1415                data[i] += (self.jitter_size/(50.0*(maxVal-minVal or 1)))*(numpy.random.random(len(self.raw_data)) - 0.5)
1416        return data
1417   
1418    getOriginalData = get_original_data
1419   
1420    def get_original_subset_data(self, indices):
1421        data = self.original_subset_data.take(indices, axis = 0)
1422        for i, ind in enumerate(indices):
1423            [minVal, maxVal] = self.attr_values[self.raw_subset_data.domain[ind].name]
1424            if self.data_domain[ind].varType == Orange.core.VarTypes.Discrete:
1425                data[i] += (self.jitter_size/(50.0*max(1, maxVal)))*(numpy.random.random(len(self.raw_subset_data)) - 0.5)
1426            elif self.data_domain[ind].varType == Orange.core.VarTypes.Continuous and self.jitter_continuous:
1427                data[i] += (self.jitter_size/(50.0*(maxVal-minVal or 1)))*(numpy.random.random(len(self.raw_subset_data)) - 0.5)
1428        return data
1429
1430    getOriginalSubsetData = get_original_subset_data
1431
1432    @deprecated_keywords({"xAttr": "xattr", "yAttr": "yattr"})
1433    def get_xy_data_positions(self, xattr, yattr):
1434        """
1435        Create x-y projection of attributes in attrlist.
1436       
1437        """
1438        xattr_index, yattr_index = self.attribute_name_index[xattr], self.attribute_name_index[yattr]
1439
1440        xdata = self.scaled_data[xattr_index].copy()
1441        ydata = self.scaled_data[yattr_index].copy()
1442       
1443        if self.data_domain[xattr_index].varType == Orange.core.VarTypes.Discrete: xdata = ((xdata * 2*len(self.data_domain[xattr_index].values)) - 1.0) / 2.0
1444        else:  xdata = xdata * (self.attr_values[xattr][1] - self.attr_values[xattr][0]) + float(self.attr_values[xattr][0])
1445
1446        if self.data_domain[yattr_index].varType == Orange.core.VarTypes.Discrete: ydata = ((ydata * 2*len(self.data_domain[yattr_index].values)) - 1.0) / 2.0
1447        else:  ydata = ydata * (self.attr_values[yattr][1] - self.attr_values[yattr][0]) + float(self.attr_values[yattr][0])
1448        return (xdata, ydata)
1449   
1450    getXYDataPositions = get_xy_data_positions
1451   
1452    @deprecated_keywords({"xAttr": "xattr", "yAttr": "yattr"})
1453    def get_xy_subset_data_positions(self, xattr, yattr):
1454        """
1455        Create x-y projection of attributes in attr_list.
1456       
1457        """
1458        xattr_index, yattr_index = self.attribute_name_index[xattr], self.attribute_name_index[yattr]
1459
1460        xdata = self.scaled_subset_data[xattr_index].copy()
1461        ydata = self.scaled_subset_data[yattr_index].copy()
1462       
1463        if self.data_domain[xattr_index].varType == Orange.core.VarTypes.Discrete: xdata = ((xdata * 2*len(self.data_domain[xattr_index].values)) - 1.0) / 2.0
1464        else:  xdata = xdata * (self.attr_values[xattr][1] - self.attr_values[xattr][0]) + float(self.attr_values[xattr][0])
1465
1466        if self.data_domain[yattr_index].varType == Orange.core.VarTypes.Discrete: ydata = ((ydata * 2*len(self.data_domain[yattr_index].values)) - 1.0) / 2.0
1467        else:  ydata = ydata * (self.attr_values[yattr][1] - self.attr_values[yattr][0]) + float(self.attr_values[yattr][0])
1468        return (xdata, ydata)
1469   
1470    getXYSubsetDataPositions = get_xy_subset_data_positions
1471   
1472    @deprecated_keywords({"attrIndices": "attr_indices",
1473                          "settingsDict": "settings_dict"})
1474    def get_projected_point_position(self, attr_indices, values, **settings_dict):
1475        """
1476        For attributes in attr_indices and values of these attributes in values
1477        compute point positions this function has more sense in radviz and
1478        polyviz methods. settings_dict has to be because radviz and polyviz have
1479        this parameter.
1480        """
1481        return values
1482
1483    getProjectedPointPosition = get_projected_point_position
1484
1485    @deprecated_keywords({"attrIndices": "attr_indices",
1486                          "settingsDict": "settings_dict"})
1487    def create_projection_as_example_table(self, attr_indices, **settings_dict):
1488        """
1489        Create the projection of attribute indices given in attr_indices and
1490        create an example table with it.
1491       
1492        """
1493        if self.data_has_class:
1494            domain = settings_dict.get("domain") or \
1495                     Orange.data.Domain([Orange.feature.Continuous(self.data_domain[attr_indices[0]].name),
1496                                         Orange.feature.Continuous(self.data_domain[attr_indices[1]].name),
1497                                         Orange.feature.Discrete(self.data_domain.class_var.name,
1498                                                                       values = get_variable_values_sorted(self.data_domain.class_var))])
1499        else:
1500            domain = settings_dict.get("domain") or \
1501                     Orange.data.Domain([Orange.feature.Continuous(self.data_domain[attr_indices[0]].name),
1502                                         Orange.feature.Continuous(self.data_domain[attr_indices[1]].name)])
1503
1504        data = self.create_projection_as_numeric_array(attr_indices,
1505                                                       **settings_dict)
1506        if data != None:
1507            return Orange.data.Table(domain, data)
1508        else:
1509            return Orange.data.Table(domain)
1510
1511    createProjectionAsExampleTable = create_projection_as_example_table
1512
1513    @deprecated_keywords({"attrIndices": "attr_indices",
1514                          "settingsDict": "settings_dict"})
1515    def create_projection_as_example_table_3D(self, attr_indices, **settings_dict):
1516        """
1517        Create the projection of attribute indices given in attr_indices and
1518        create an example table with it.
1519       
1520        """
1521        if self.data_has_class:
1522            domain = settings_dict.get("domain") or \
1523                     Orange.data.Domain([Orange.feature.Continuous(self.data_domain[attr_indices[0]].name),
1524                                         Orange.feature.Continuous(self.data_domain[attr_indices[1]].name),
1525                                         Orange.feature.Continuous(self.data_domain[attr_indices[2]].name),
1526                                         Orange.feature.Discrete(self.data_domain.class_var.name,
1527                                                                       values = get_variable_values_sorted(self.data_domain.class_var))])
1528        else:
1529            domain = settings_dict.get("domain") or \
1530                     Orange.data.Domain([Orange.feature.Continuous(self.data_domain[attr_indices[0]].name),
1531                                         Orange.feature.Continuous(self.data_domain[attr_indices[1]].name),
1532                                         Orange.feature.Continuous(self.data_domain[attr_indices[2]].name)])
1533
1534        data = self.create_projection_as_numeric_array_3D(attr_indices,
1535                                                          **settings_dict)
1536        if data != None:
1537            return Orange.data.Table(domain, data)
1538        else:
1539            return Orange.data.Table(domain)
1540
1541    createProjectionAsExampleTable3D = create_projection_as_example_table_3D
1542
1543    @deprecated_keywords({"attrIndices": "attr_indices",
1544                          "settingsDict": "settings_dict",
1545                          "validData": "valid_data",
1546                          "classList": "class_list",
1547                          "jutterSize": "jitter_size"})
1548    def create_projection_as_numeric_array(self, attr_indices, **settings_dict):
1549        valid_data = settings_dict.get("valid_data")
1550        class_list = settings_dict.get("class_list")
1551        jitter_size = settings_dict.get("jitter_size", 0.0)
1552
1553        if valid_data == None:
1554            valid_data = self.get_valid_list(attr_indices)
1555        if sum(valid_data) == 0:
1556            return None
1557
1558        if class_list == None and self.data_has_class:
1559            class_list = self.original_data[self.data_class_index]
1560
1561        xarray = self.no_jittering_scaled_data[attr_indices[0]]
1562        yarray = self.no_jittering_scaled_data[attr_indices[1]]
1563        if jitter_size > 0.0:
1564            xarray += (numpy.random.random(len(xarray))-0.5)*jitter_size
1565            yarray += (numpy.random.random(len(yarray))-0.5)*jitter_size
1566        if class_list != None:
1567            data = numpy.compress(valid_data, numpy.array((xarray, yarray, class_list)), axis = 1)
1568        else:
1569            data = numpy.compress(valid_data, numpy.array((xarray, yarray)), axis = 1)
1570        data = numpy.transpose(data)
1571        return data
1572
1573    createProjectionAsNumericArray = create_projection_as_numeric_array
1574
1575    @deprecated_keywords({"attrIndices": "attr_indices",
1576                          "settingsDict": "settings_dict",
1577                          "validData": "valid_data",
1578                          "classList": "class_list",
1579                          "jutterSize": "jitter_size"})
1580    def create_projection_as_numeric_array_3D(self, attr_indices, **settings_dict):
1581        valid_data = settings_dict.get("valid_data")
1582        class_list = settings_dict.get("class_list")
1583        jitter_size = settings_dict.get("jitter_size", 0.0)
1584
1585        if valid_data == None:
1586            valid_data = self.get_valid_list(attr_indices)
1587        if sum(valid_data) == 0:
1588            return None
1589
1590        if class_list == None and self.data_has_class:
1591            class_list = self.original_data[self.data_class_index]
1592
1593        xarray = self.no_jittering_scaled_data[attr_indices[0]]
1594        yarray = self.no_jittering_scaled_data[attr_indices[1]]
1595        zarray = self.no_jittering_scaled_data[attr_indices[2]]
1596        if jitter_size > 0.0:
1597            xarray += (numpy.random.random(len(xarray))-0.5)*jitter_size
1598            yarray += (numpy.random.random(len(yarray))-0.5)*jitter_size
1599            zarray += (numpy.random.random(len(zarray))-0.5)*jitter_size
1600        if class_list != None:
1601            data = numpy.compress(valid_data, numpy.array((xarray, yarray, zarray, class_list)), axis = 1)
1602        else:
1603            data = numpy.compress(valid_data, numpy.array((xarray, yarray, zarray)), axis = 1)
1604        data = numpy.transpose(data)
1605        return data
1606
1607    createProjectionAsNumericArray3D = create_projection_as_numeric_array_3D
1608
1609    @deprecated_keywords({"attributeNameOrder": "attribute_name_order",
1610                          "addResultFunct": "add_result_funct"})
1611    def get_optimal_clusters(self, attribute_name_order, add_result_funct):
1612        if not self.data_has_class or self.data_has_continuous_class:
1613            return
1614       
1615        jitter_size = 0.001 * self.clusterOptimization.jitterDataBeforeTriangulation
1616        domain = Orange.data.Domain([Orange.feature.Continuous("xVar"),
1617                                     Orange.feature.Continuous("yVar"),
1618                                    self.data_domain.class_var])
1619
1620        # init again, in case that the attribute ordering took too much time
1621        self.scatterWidget.progressBarInit()
1622        start_time = time.time()
1623        count = len(attribute_name_order)*(len(attribute_name_order)-1)/2
1624        test_index = 0
1625
1626        for i in range(len(attribute_name_order)):
1627            for j in range(i):
1628                try:
1629                    attr1 = self.attribute_name_index[attribute_name_order[j]]
1630                    attr2 = self.attribute_name_index[attribute_name_order[i]]
1631                    test_index += 1
1632                    if self.clusterOptimization.isOptimizationCanceled():
1633                        secs = time.time() - start_time
1634                        self.clusterOptimization.setStatusBarText("Evaluation stopped (evaluated %d projections in %d min, %d sec)"
1635                                                                  % (test_index, secs/60, secs%60))
1636                        self.scatterWidget.progressBarFinished()
1637                        return
1638
1639                    data = self.create_projection_as_example_table([attr1, attr2],
1640                                                                   domain = domain,
1641                                                                   jitter_size = jitter_size)
1642                    graph, valuedict, closuredict, polygon_vertices_dict, enlarged_closure_dict, other_dict = self.clusterOptimization.evaluateClusters(data)
1643
1644                    all_value = 0.0
1645                    classes_dict = {}
1646                    for key in valuedict.keys():
1647                        add_result_funct(valuedict[key], closuredict[key],
1648                                         polygon_vertices_dict[key],
1649                                         [attribute_name_order[i],
1650                                          attribute_name_order[j]],
1651                                          int(graph.objects[polygon_vertices_dict[key][0]].getclass()),
1652                                          enlarged_closure_dict[key], other_dict[key])
1653                        classes_dict[key] = int(graph.objects[polygon_vertices_dict[key][0]].getclass())
1654                        all_value += valuedict[key]
1655                    add_result_funct(all_value, closuredict, polygon_vertices_dict,
1656                                     [attribute_name_order[i], attribute_name_order[j]],
1657                                     classes_dict, enlarged_closure_dict, other_dict)     # add all the clusters
1658                   
1659                    self.clusterOptimization.setStatusBarText("Evaluated %d projections..."
1660                                                              % (test_index))
1661                    self.scatterWidget.progressBarSet(100.0*test_index/float(count))
1662                    del data, graph, valuedict, closuredict, polygon_vertices_dict, enlarged_closure_dict, other_dict, classes_dict
1663                except:
1664                    type, val, traceback = sys.exc_info()
1665                    sys.excepthook(type, val, traceback)  # print the exception
1666       
1667        secs = time.time() - start_time
1668        self.clusterOptimization.setStatusBarText("Finished evaluation (evaluated %d projections in %d min, %d sec)" % (test_index, secs/60, secs%60))
1669        self.scatterWidget.progressBarFinished()
1670   
1671    getOptimalClusters = get_optimal_clusters
1672
1673ScaleScatterPlotData = deprecated_members({"getOriginalData": "get_original_data",
1674                                           "getOriginalSubsetData": "get_original_subset_data",
1675                                           "getXYDataPositions": "get_xy_data_positions",
1676                                           "getXYSubsetDataPositions": "get_xy_subset_data_positions",
1677                                           "getProjectedPointPosition": "get_projected_point_position",
1678                                           "createProjectionAsExampleTable": "create_projection_as_example_table",
1679                                           "createProjectionAsExampleTable3D": "create_projection_as_example_table_3D",
1680                                           "createProjectionAsNumericArray": "create_projection_as_numeric_array",
1681                                           "createProjectionAsNumericArray3D": "create_projection_as_numeric_array_3D",
1682                                           "getOptimalClusters": "get_optimal_clusters"
1683                                           })(ScaleScatterPlotData)
Note: See TracBrowser for help on using the repository browser.