Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
e0dbcbd
added example of big 1D array
gdementen Oct 31, 2017
5660a99
when using the scrollwheel on filter comboboxes, only emit one signal…
gdementen Nov 10, 2017
09f4927
fixed diff_checkbox state being ignored when switching arrays
gdementen Nov 8, 2017
49a5d11
fixed compare+diffonly when stack failed
gdementen Nov 8, 2017
f5a0465
fixed LArrayDataAdapter.get_xlabels being slow on large 1D arrays (is…
gdementen Nov 8, 2017
713869a
prevent "filters" label from appearing for scalar (0D) arrays
gdementen Nov 8, 2017
244151c
made large 1D arrays display faster by not creating the filter combob…
gdementen Nov 8, 2017
ef17c33
use min/max instead of nanmin/nanmax because nans are already filtere…
gdementen Nov 8, 2017
d3901b1
select first row in compare(sessions)
gdementen Nov 8, 2017
c535158
fixed readonly being always False when editing arrays (doh!)
gdementen Nov 8, 2017
4a4b2fd
do not update_digits_scientific on accept_changes (it makes no sense)
gdementen Nov 8, 2017
049edec
made LinearGradient more foregiving (unsure it is a good idea)
gdementen Nov 8, 2017
21ef4c8
reworked editor internals to avoid calling update methods several tim…
gdementen Oct 26, 2017
f8bc4af
simplified and optimized larray editor internals (issue #93)
gdementen Nov 9, 2017
eea054d
made switching to a big array (much) faster by not computing its min/max
gdementen Nov 9, 2017
77ede67
cosmetic improvements to about dialog
gdementen Nov 10, 2017
52eaf2b
removed useless line (view, edit and compare are also in larray)
gdementen Nov 10, 2017
febd9f5
added support for coloring object arrays (only use numeric values)
gdementen Nov 10, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions larray_editor/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@ def make_demo(width=20, ball_radius=5, path_radius=5, steps=30):
arr_obj = ndtest((2, 3)).astype(object)
arr_str = ndtest((2, 3)).astype(str)
big = ndtest((1000, 1000, 500))
big1d = ndrange(1000000)
# force big1d.axes[0]._mapping to be created so that we do not measure that delay in the editor
big1d[{}]

# test autoresizing
long_labels = zeros('a=a_long_label,another_long_label; b=this_is_a_label,this_is_another_one')
Expand Down
69 changes: 33 additions & 36 deletions larray_editor/arrayadapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,24 @@

import numpy as np
import larray as la
from larray_editor.utils import Product, _LazyNone, _LazyDimLabels

from larray_editor.utils import Product, _LazyDimLabels


class LArrayDataAdapter(object):
def __init__(self, axes_model, xlabels_model, ylabels_model, data_model,
data=None, changes=None, current_filter=None, bg_gradient=None, bg_value=None):
def __init__(self, axes_model, xlabels_model, ylabels_model, data_model):
# set models
self.axes_model = axes_model
self.xlabels_model = xlabels_model
self.ylabels_model = ylabels_model
self.data_model = data_model
# set current filter
if current_filter is None:
current_filter = {}
assert isinstance(current_filter, dict)
self.current_filter = current_filter
# set changes
if changes is None:
changes = {}
self.set_changes(changes)
# set data
if data is None:
data = np.empty((0, 0), dtype=np.int8)
self.set_data(data, bg_value, current_filter)

def set_changes(self, changes=None):
assert isinstance(changes, dict)
self.changes = changes

# these are not valid values, but should overwritten by set_data which must be called before the adapter is used
self.current_filter = None
self.changes = None
self.la_data = None
self.bg_value = None
self.filtered_data = None

def get_axes_names(self):
return self.filtered_data.axes.display_names
Expand All @@ -39,7 +29,7 @@ def get_axes(self):
# test self.filtered_data.size == 0 is required in case an instance built as LArray([]) is passed
# test len(axes) == 0 is required when a user filters until to get a scalar
if self.filtered_data.size == 0 or len(axes) == 0:
return None
return [[]]
else:
axes_names = axes.display_names
if len(axes_names) >= 2:
Expand All @@ -49,14 +39,16 @@ def get_axes(self):
def get_xlabels(self):
axes = self.filtered_data.axes
if self.filtered_data.size == 0 or len(axes) == 0:
return None
return [[]]
else:
return [[label] for label in axes.labels[-1]]
# this is a lazy equivalent of:
# return [(label,) for label in axes.labels[-1]]
return Product([axes.labels[-1]])

def get_ylabels(self):
axes = self.filtered_data.axes
if self.filtered_data.size == 0 or len(axes) == 0:
return None
return [[]]
elif len(axes) == 1:
return [['']]
else:
Expand Down Expand Up @@ -99,34 +91,37 @@ def get_bg_value_2D(self, shape_2D):
# XXX: or create two methods?:
# - set_data (which reset the current filter)
# - update_data (which sets new data but keeps current filter unchanged)
def set_data(self, data, bg_value=None, current_filter=None):
if data is None:
data = la.LArray([])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why moving these 2 lines (if data is None: ...) in ArrayEditorWidget?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like I tried to explain in the commit comments: just because it makes the internal api simpler: you know what you get. In general, external API should accept as many useful things as possible, internal API should be as simple as possible.

if current_filter is None:
self.current_filter = {}
def set_data(self, data, bg_value=None):
assert isinstance(data, la.LArray)
self.current_filter = {}
self.changes = {}
self.la_data = la.aslarray(data)
self.bg_value = la.aslarray(bg_value) if bg_value is not None else None
self.update_filtered_data(current_filter, reset_minmax=True)
self.update_filtered_data()
self.data_model.reset_minmax()
self.data_model.reset()

def update_filtered_data(self, current_filter=None, reset_minmax=False):
if current_filter is not None:
assert isinstance(current_filter, dict)
self.current_filter = current_filter
def update_filtered_data(self):
assert isinstance(self.la_data, la.LArray)
self.filtered_data = self.la_data[self.current_filter]

if np.isscalar(self.filtered_data):
self.filtered_data = la.aslarray(self.filtered_data)

axes = self.get_axes()
xlabels = self.get_xlabels()
ylabels = self.get_ylabels()
data_2D = self.get_2D_data()
changes_2D = self.get_changes_2D()
bg_value_2D = self.get_bg_value_2D(data_2D.shape)

self.axes_model.set_data(axes)
self.xlabels_model.set_data(xlabels)
self.ylabels_model.set_data(ylabels)
self.data_model.set_data(data_2D, changes_2D, reset_minmax=reset_minmax)
self.data_model.set_bg_value(bg_value_2D)
# using the protected version of the method to avoid calling reset() several times
self.data_model._set_data(data_2D)
self.data_model._set_changes(changes_2D)
self.data_model._set_bg_value(bg_value_2D)

def get_data(self):
return self.la_data
Expand Down Expand Up @@ -221,6 +216,7 @@ def change_filter(self, axis, indices):
else:
self.current_filter[axis_id] = axis.labels[indices]
self.update_filtered_data()
self.data_model.reset()

def clear_changes(self):
self.changes.clear()
Expand All @@ -236,6 +232,7 @@ def accept_changes(self):
self.la_data.i[axes.translate_full_key(k)] = v
# update models
self.update_filtered_data()
self.data_model.reset()
# clear changes
self.clear_changes()
# return modified data
Expand Down
Loading