Skip to content

Commit

Permalink
[WIP] widgets: I/O summaries
Browse files Browse the repository at this point in the history
  • Loading branch information
ales-erjavec committed Sep 5, 2017
1 parent 992b85b commit 3231d90
Show file tree
Hide file tree
Showing 16 changed files with 605 additions and 25 deletions.
13 changes: 13 additions & 0 deletions Orange/widgets/data/owconcatenate.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ def set_more_data(self, data=None, id=None):

def handleNewSignals(self):
self.mergebox.setDisabled(self.primary_data is not None)
if self.primary_data is not None and not self.more_data:
short = "Primary ({} rows)".format(len(self.primary_data))
elif self.primary_data is not None and self.more_data:
short = "Primary + {} extra tables".format(len(self.more_data))
elif self.primary_data is None and self.more_data:
short = "{} tables".format(len(self.more_data))
else:
short = None
self.info.set_input_summary(short)
self.apply()

def apply(self):
Expand Down Expand Up @@ -184,6 +193,10 @@ def apply(self):
data = None

self.Outputs.data.send(data)
if data is None:
self.info.set_output_summary(None)
else:
self.info.set_output_summary("{} rows".format(len(data)))

def _merge_type_changed(self, ):
if self.primary_data is None and self.more_data:
Expand Down
11 changes: 11 additions & 0 deletions Orange/widgets/data/owdatasampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,18 @@ def set_data(self, dataset):
('~', dataset.approx_len()) if sql else
('', len(dataset)))))
if not sql:
nrows_s = "{}".format(len(dataset))
self.sampleSizeSpin.setMaximum(len(dataset))
self.updateindices()
else:
nrows_s = "~{}".format(dataset.approx_len())
self.info.set_input_summary(nrows_s + " rows")
self.dataInfoLabel.setText(
nrows_s + ' instances in input data set.')
else:
self.dataInfoLabel.setText('No data on input.')
self.outputInfoLabel.setText('')
self.info.set_input_summary(self.info.NoInput)
self.indices = None
self.clear_messages()
self.commit()
Expand Down Expand Up @@ -228,6 +235,10 @@ def commit(self):
self.remaining_instances = len(other)
self.Outputs.data_sample.send(sample)
self.Outputs.remaining_data.send(other)
if sample is not None:
self.info.set_output_summary("{} rows".format(len(sample)))
else:
self.info.set_output_summary(self.info.NoOutput)

def updateindices(self):
self.Error.clear()
Expand Down
12 changes: 12 additions & 0 deletions Orange/widgets/data/owdiscretize.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,12 @@ def set_data(self, data):
self._update_points()
else:
self._clear()
if self.data is None:
self.info.set_input_summary(self.info.NoInput)
else:
from .owselectcolumns import summarize
self.info.set_input_summary(
"{}x({})".format(len(self.data), summarize(self.data.domain, True)))
self.unconditional_commit()

def _initialize(self, data):
Expand Down Expand Up @@ -471,6 +477,12 @@ def commit(self):
if self.data is not None and len(self.data):
domain = self.discretized_domain()
output = self.data.transform(domain)
if output is None:
self.info.set_output_summary(None)
else:
from .owselectcolumns import summarize
self.info.set_output_summary(
"{}x({})".format(len(output), summarize(output.domain)))
self.Outputs.data.send(output)

def storeSpecificSettings(self):
Expand Down
29 changes: 23 additions & 6 deletions Orange/widgets/data/owfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def __init__(self):
url_combo.activated.connect(self._url_set)

box = gui.vBox(self.controlArea, "Info")
self.info = gui.widgetLabel(box, 'No data loaded.')
self.info_label = gui.widgetLabel(box, 'No data loaded.')
self.warnings = gui.widgetLabel(box, '')

box = gui.widgetBox(self.controlArea, "Columns (Double click to edit)")
Expand Down Expand Up @@ -223,6 +223,7 @@ def __init__(self):
self.Warning.file_too_big()
return

self.info.set_output_summary(self.info.NoOutput)
QTimer.singleShot(0, self.load_data)

def sizeHint(self):
Expand Down Expand Up @@ -285,7 +286,8 @@ def load_data(self):
if self.last_path() and not os.path.exists(self.last_path()):
self.Error.file_not_found()
self.Outputs.data.send(None)
self.info.setText("No data.")
self.info.set_output_summary(self.info.NoOutput)
self.info_label.setText("No data.")
return

error = None
Expand All @@ -294,7 +296,7 @@ def load_data(self):
if self.reader is None:
self.data = None
self.Outputs.data.send(None)
self.info.setText("No data.")
self.info_label.setText("No data.")
self.sheet_box.hide()
return
except Exception as ex:
Expand All @@ -313,12 +315,14 @@ def load_data(self):
if error:
self.data = None
self.Outputs.data.send(None)
self.info.setText("An error occurred:\n{}".format(error))
self.info.set_output_summary(
self.info.NoOutput._replace(text="<em>Error</em>",
textFormat=Qt.RichText))
self.info_label.setText("An error occurred:\n{}".format(error))
self.sheet_box.hide()
return

self.info.setText(self._describe(data))

self.info_label.setText(self._describe(data))
self.loaded_file = self.last_path()
add_origin(data, self.loaded_file)
self.data = data
Expand Down Expand Up @@ -418,6 +422,19 @@ def apply_domain_edit(self):
table.attributes = getattr(self.data, 'attributes', {})

self.Outputs.data.send(table)
if table is None:
self.info.set_output_summary(self.info.NoOutput)
else:
short = "{}x({}+{}+{})".format(
len(table), len(table.domain.attributes),
len(table.domain.class_vars), len(table.domain.metas))

self.info.set_output_summary(short, details=self._describe(table),
format=Qt.RichText)
from .owmergedata import summarize_data
self.info.set_output_summary(
short, summarize_data(table), format=Qt.RichText
)
self.apply_button.setEnabled(False)

def get_widget_name_extension(self):
Expand Down
47 changes: 47 additions & 0 deletions Orange/widgets/data/owmergedata.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from enum import IntEnum
from itertools import chain, product, tee

from AnyQt.QtCore import Qt
from AnyQt.QtWidgets import QApplication, QStyle, QSizePolicy

import numpy as np
Expand Down Expand Up @@ -219,6 +220,27 @@ def setExtraData(self, data):
self._find_best_match()

def handleNewSignals(self):
short = []
detailed = None
if self.data is not None:
short += ["primary table ({}x{})"
.format(len(self.data),
len(self.data.domain.variables) +
len(self.data.domain.metas))]
if self.extra_data is not None:
short += ["extra table ({}x{})"
.format(len(self.extra_data),
len(self.extra_data.domain.variables) +
len(self.extra_data.domain.metas))]
if short:
items = [("Primary data", summarize_data(self.data)),
("Extra data", summarize_data(self.extra_data))]
detailed = render_field_list(items, tag="dl")
if short:
self.info.set_input_summary(
", ".join(short).capitalize(), details=detailed, format=Qt.RichText)
else:
self.info.set_input_summary(self.info.NoInput)
self._invalidate()

def dataInfoText(self, data):
Expand All @@ -242,6 +264,19 @@ def commit(self):
if len(set(var_names)) != len(var_names):
self.Warning.duplicate_names()
self.Outputs.data.send(merged_data)
if merged_data is None:
self.info.set_output_summary(self.info.NoOutput)
else:
self.info.set_output_summary(
"{} rows, {} columns <sub>({}+{}+{})</sub>".format(
len(merged_data),
len(merged_data.domain.variables) +
len(merged_data.domain.metas),
len(merged_data.domain.attributes),
len(merged_data.domain.class_vars),
len(merged_data.domain.metas)),
format=Qt.RichText
)

def _invalidate(self):
self.commit()
Expand Down Expand Up @@ -390,6 +425,18 @@ def prepare(arr, inds, str_cols):
return res



from .owselectcolumns import summarize_domain_long_items, \
render_field_list

def summarize_data(data):
if data is None:
return "none"
else:
return render_field_list(
[("Rows", str(len(data)))] +
summarize_domain_long_items(data.domain))

def main():
app = QApplication([])
w = OWMergeData()
Expand Down
3 changes: 3 additions & 0 deletions Orange/widgets/data/owpaintdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,7 @@ def commit(self):
data = np.array(self.data)
if len(data) == 0:
self.Outputs.data.send(None)
self.info.set_output_summary(self.info.NoOutput)
return
if self.hasAttr2:
X, Y = data[:, :2], data[:, 2]
Expand All @@ -1273,6 +1274,8 @@ def commit(self):
data = Orange.data.Table.from_numpy(domain, X)
data.name = self.table_name
self.Outputs.data.send(data)
self.info.set_output_summary(
"{} row{}".format(len(data), "s" if len(data) != 1 else ""))

def sizeHint(self):
sh = super().sizeHint()
Expand Down
71 changes: 71 additions & 0 deletions Orange/widgets/data/owpreprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,15 @@ def set_data(self, data=None):
self.data = data

def handleNewSignals(self):
from .owmergedata import summarize_data
if self.data is not None:
self.info.set_input_summary(
summary_short(self.data),
summarize_data(self.data),
format=Qt.RichText
)
else:
self.info.set_input_summary(self.info.NoInput)
self.apply()

def __activated(self, index):
Expand Down Expand Up @@ -1191,6 +1200,26 @@ def apply(self):

self.Outputs.preprocessor.send(preprocessor)
self.Outputs.preprocessed_data.send(data)
short = []
detailed = []
if preprocessor is not None:
short += ["preprocessor"]
detailed += [("Preprocesor", repr(preprocessor))]
if data is not None:
short += ["data"]
from .owmergedata import summarize_data
detailed += [("Data", summarize_data(data))]

if short:
short = " and ".join(short).capitalize()
from .owselectcolumns import render_field_list

self.info.set_output_summary(
short, render_field_list(detailed, tag="dl"),
format=Qt.RichText
)
else:
self.info.set_output_summary(self.info.NoOutput)

def commit(self):
if not self._invalidated:
Expand Down Expand Up @@ -1245,6 +1274,48 @@ def send_report(self):
self.report_items("Settings", pp)


def summary_shape_inline(data):
"""
Return a short inline shape summary of the `data`.
The domain shape is reported as 3
Parameters
----------
data : Orange.data.Table
Returns
-------
text : str
Example
-------
>>> hd = Orange.data.Table("heart_disease")
>>> summary_short(hd)
'303 × (13 | 1)'
"""
# 12 x 5 # X only
# 12 x (4 | 1) # X + Y
# 12 x (4 | 1 : 2) # X + Y + M
# 12 x (0 | 1 : 1)
# 12 x (0 : 1)
# 12 x 0
N = len(data)
M_a = len(data.domain.attributes)
M_c = len(data.domain.class_vars)
M_m = len(data.domain.metas)
fmt = ["{M_a}"]
if M_c:
fmt += ["| {M_c}"]
if M_m:
fmt += [": {M_m}"]
fmt = " ".join(fmt)
if M_c + M_m:
fmt = "(" + fmt + ")"
return ("{N} \N{MULTIPLICATION SIGN} " + fmt).format(N=N, M_a=M_a, M_c=M_c, M_m=M_m)

summary_short = summary_shape_inline


def test_main(argv=sys.argv):
argv = list(argv)
app = QApplication(argv)
Expand Down
Loading

0 comments on commit 3231d90

Please sign in to comment.