source: orange/Orange/data/preprocess/scaling.py @ 10651:4f6fcf57db06

Revision 10651:4f6fcf57db06, 81.3 KB checked in by markotoplak, 2 years ago (diff)

Moved caching, collections, debugging, fileutil, r, testing from misc to utils.

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