1import numpy as np
2from Orange.data import Domain, DiscreteVariable
3from Orange.data.util import get_unique_names
4
5ANNOTATED_DATA_SIGNAL_NAME = "Data"
6ANNOTATED_DATA_FEATURE_NAME = "Selected"
7
8
9def add_columns(domain, attributes=(), class_vars=(), metas=()):
10    """Construct a new domain with new columns added to the specified place
11
12    Parameters
13    ----------
14    domain : Domain
15        source domain
16    attributes
17        list of variables to append to attributes from source domain
18    class_vars
19        list of variables to append to class_vars from source domain
20    metas
21        list of variables to append to metas from source domain
22
23    Returns
24    -------
25    Domain
26    """
27    attributes = domain.attributes + tuple(attributes)
28    class_vars = domain.class_vars + tuple(class_vars)
29    metas = domain.metas + tuple(metas)
30    return Domain(attributes, class_vars, metas)
31
32
33def _table_with_annotation_column(data, values, column_data, var_name):
34    var = DiscreteVariable(get_unique_names(data.domain, var_name), values)
35    class_vars, metas = data.domain.class_vars, data.domain.metas
36    if not data.domain.class_vars:
37        class_vars += (var, )
38    else:
39        metas += (var, )
40    domain = Domain(data.domain.attributes, class_vars, metas)
41    table = data.transform(domain)
42    table[:, var] = column_data.reshape((len(data), 1))
43    return table
44
45
46def create_annotated_table(data, selected_indices):
47    """
48    Returns data with concatenated flag column. Flag column represents
49    whether data instance has been selected (Yes) or not (No), which is
50    determined in selected_indices parameter.
51
52    :param data: Table
53    :param selected_indices: list or ndarray
54    :return: Table
55    """
56    if data is None:
57        return None
58    annotated = np.zeros((len(data), 1))
59    if selected_indices is not None:
60        annotated[selected_indices] = 1
61    return _table_with_annotation_column(
62        data, ("No", "Yes"), annotated, ANNOTATED_DATA_FEATURE_NAME)
63
64
65def create_groups_table(data, selection,
66                        include_unselected=True,
67                        var_name=ANNOTATED_DATA_FEATURE_NAME,
68                        values=None):
69    if data is None:
70        return None
71    max_sel = np.max(selection)
72    if values is None:
73        values = ["G{}".format(i + 1) for i in range(max_sel)]
74        if include_unselected:
75            values.append("Unselected")
76    if include_unselected:
77        # Place Unselected instances in the "last group", so that the group
78        # colors and scatter diagram marker colors will match
79        mask = (selection != 0)
80        selection = selection.copy()
81        selection[mask] = selection[mask] - 1
82        selection[~mask] = selection[~mask] = max_sel
83    else:
84        mask = np.flatnonzero(selection)
85        data = data[mask]
86        selection = selection[mask] - 1
87    return _table_with_annotation_column(data, values, selection, var_name)
88