mwcraig / reducer

Friendly professional-level data reduction...documentation here:
https://reducer.readthedocs.org
BSD 3-Clause "New" or "Revised" License
26 stars 10 forks source link

layout and behaviour of widgets in v0.3.2 #140

Closed StuartLittlefair closed 6 years ago

StuartLittlefair commented 7 years ago

With reducer v0.3.2, jupyter notebook 4.2.3 and ipywidgets 5.2.2 the widgets are unusable and layout is scrambled.

The screenshot below shows the layout of the combiner gui, the reduction gui is similar.

screen shot 2016-10-31 at 16 21 31

In addition, any attempt to click a button in the above layout causes the following error

---------------------------------------------------------------------------
TraitError                                Traceback (most recent call last)
/usr/local/lib/python3.5/site-packages/ipywidgets/widgets/widget.py in _handle_msg(self, msg)
    426                 for i,k in enumerate(data.get('buffer_keys', [])):
    427                     sync_data[k] = msg['buffers'][i]
--> 428                 self.set_state(sync_data) # handles all methods
    429 
    430         # Handle a state request.

/usr/local/lib/python3.5/site-packages/ipywidgets/widgets/widget.py in set_state(self, sync_data)
    305                     from_json = self.trait_metadata(name, 'from_json',
    306                                                     self._trait_from_json)
--> 307                     self.set_trait(name, from_json(sync_data[name], self))
    308 
    309     def send(self, content, buffers=None):

/usr/local/Cellar/python3/3.5.2_2/Frameworks/Python.framework/Versions/3.5/lib/python3.5/contextlib.py in __exit__(self, type, value, traceback)
     64         if type is None:
     65             try:
---> 66                 next(self.gen)
     67             except StopIteration:
     68                 return

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in hold_trait_notifications(self)
   1127                 for changes in cache.values():
   1128                     for change in changes:
-> 1129                         self.notify_change(change)
   1130 
   1131     def _notify_trait(self, name, old_value, new_value):

/usr/local/lib/python3.5/site-packages/ipywidgets/widgets/widget.py in notify_change(self, change)
    366                 # Send new state to front-end
    367                 self.send_state(key=name)
--> 368         LoggingConfigurable.notify_change(self, change)
    369 
    370     #-------------------------------------------------------------------------

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in notify_change(self, change)
   1172                 c = getattr(self, c.name)
   1173 
-> 1174             c(change)
   1175 
   1176     def _add_notifiers(self, handler, name, type):

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in __call__(self, change)
    694         # The wrapper is callable
    695         if self.nargs == 0:
--> 696             self.cb()
    697         elif self.nargs == 1:
    698             self.cb(change.name)

/usr/local/lib/python3.5/site-packages/reducer/gui.py in flip_state()
    212     def _ping_handler(self):
    213         def flip_state():
--> 214             self._state_monitor.value = not self._state_monitor.value
    215 
    216         return flip_state

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in __set__(self, obj, value)
    581             raise TraitError('The "%s" trait is read-only.' % self.name)
    582         else:
--> 583             self.set(obj, value)
    584 
    585     def _validate(self, obj, value):

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in set(self, obj, value)
    570             # we explicitly compare silent to True just in case the equality
    571             # comparison above returns something other than True/False
--> 572             obj._notify_trait(self.name, old_value, new_value)
    573 
    574     def __set__(self, obj, value):

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in _notify_trait(self, name, old_value, new_value)
   1135             new=new_value,
   1136             owner=self,
-> 1137             type='change',
   1138         ))
   1139 

/usr/local/lib/python3.5/site-packages/ipywidgets/widgets/widget.py in notify_change(self, change)
    366                 # Send new state to front-end
    367                 self.send_state(key=name)
--> 368         LoggingConfigurable.notify_change(self, change)
    369 
    370     #-------------------------------------------------------------------------

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in notify_change(self, change)
   1172                 c = getattr(self, c.name)
   1173 
-> 1174             c(change)
   1175 
   1176     def _add_notifiers(self, handler, name, type):

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in __call__(self, change)
    694         # The wrapper is callable
    695         if self.nargs == 0:
--> 696             self.cb()
    697         elif self.nargs == 1:
    698             self.cb(change.name)

/usr/local/lib/python3.5/site-packages/reducer/gui.py in flip_state()
    212     def _ping_handler(self):
    213         def flip_state():
--> 214             self._state_monitor.value = not self._state_monitor.value
    215 
    216         return flip_state

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in __set__(self, obj, value)
    581             raise TraitError('The "%s" trait is read-only.' % self.name)
    582         else:
--> 583             self.set(obj, value)
    584 
    585     def _validate(self, obj, value):

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in set(self, obj, value)
    570             # we explicitly compare silent to True just in case the equality
    571             # comparison above returns something other than True/False
--> 572             obj._notify_trait(self.name, old_value, new_value)
    573 
    574     def __set__(self, obj, value):

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in _notify_trait(self, name, old_value, new_value)
   1135             new=new_value,
   1136             owner=self,
-> 1137             type='change',
   1138         ))
   1139 

/usr/local/lib/python3.5/site-packages/ipywidgets/widgets/widget.py in notify_change(self, change)
    366                 # Send new state to front-end
    367                 self.send_state(key=name)
--> 368         LoggingConfigurable.notify_change(self, change)
    369 
    370     #-------------------------------------------------------------------------

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in notify_change(self, change)
   1172                 c = getattr(self, c.name)
   1173 
-> 1174             c(change)
   1175 
   1176     def _add_notifiers(self, handler, name, type):

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in __call__(self, change)
    698             self.cb(change.name)
    699         elif self.nargs == 2:
--> 700             self.cb(change.name, change.new)
    701         elif self.nargs == 3:
    702             self.cb(change.name, change.old, change.new)

/usr/local/lib/python3.5/site-packages/reducer/gui.py in set_color(name, value)
    471                 a_widget.toggle.button_style = 'success'
    472         else:
--> 473             a_widget.toggle.button_style = None
    474     return set_color

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in __set__(self, obj, value)
    581             raise TraitError('The "%s" trait is read-only.' % self.name)
    582         else:
--> 583             self.set(obj, value)
    584 
    585     def _validate(self, obj, value):

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in set(self, obj, value)
    555 
    556     def set(self, obj, value):
--> 557         new_value = self._validate(obj, value)
    558         try:
    559             old_value = obj._trait_values[self.name]

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in _validate(self, obj, value)
    587             return value
    588         if hasattr(self, 'validate'):
--> 589             value = self.validate(obj, value)
    590         if obj._cross_validation_lock is False:
    591             value = self._cross_validate(obj, value)

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in validate(self, obj, value)
   2154             value = cast_unicode_py2(value)
   2155         if not isinstance(value, six.string_types):
-> 2156             self.error(obj, value)
   2157 
   2158         for v in self.values:

/usr/local/lib/python3.5/site-packages/traitlets/traitlets.py in error(self, obj, value)
    621             e = "The '%s' trait must be %s, but a value of %r was specified." \
    622                 % (self.name, self.info(), repr_type(value))
--> 623         raise TraitError(e)
    624 
    625     def get_metadata(self, key, default=None):

TraitError: The 'button_style' trait of a ToggleButton instance must be any of ['primary', 'success', 'info', 'warning', 'danger', ''], but a value of None <class 'NoneType'> was specified.
mwcraig commented 7 years ago

Thanks for the report.

TL;DR: installing ipywidgets 4.x will fix it for now. Likely to jump directly from ipywidgets 4 to 6 interms of supported versions.

TL: The layout mechanism changed completely in ipywidgets 5. I started working on an upgrade to 5 over the summer, but hit an issue with the accordion widget (used in the image browser) that made it non-functional. That has since been fixed in ipywidgets master but (I think) won't be backported to 5.x. I just saw that ipywidgets 6.0.0b1 was released today and am checking on a release date for 6.0.0. Assuming it is no more than a month off, I'll target a reducer release for around that time that supports 6.

Not quite sure how I'll handle trying to support both 4.x and 6.x, though....may just declare 6.x to be the only supported version.

StuartLittlefair commented 7 years ago

Thanks for the prompt reply @mwcraig.

I think there may be an incompatibility between the V4.2.x of the Jupyter notebook and ipywidgets-4.x, since I get the following error with that combination

When I try to run the 5 cell in the demo notebook I got
[IPKernelApp] ERROR | No such comm target registered: jupyter.widget.version

which others have also reported, e.g here. I would downgrade my notebook version but I'm delivering a course on Sage Math Cloud so am stuck with 4.2.x. I'll keep an eye open for ipywidgets v6 support...

mwcraig commented 7 years ago

Odd; I'm running notebook 4.2.2 and not getting that error.

In any event, how soon do you need an update? Sounds like it will be more than a month until 6.0 is out. I can carve out some time in the next couple weeks to work on getting out a beta release that is at least mostly compatible with ipywidgets 5 (and fully compatible with 6).

StuartLittlefair commented 7 years ago

That is bizarre. I'll try and understand the source of my error more.

Don't rush for an update. I'm teaching a class using reducer in three weeks but if I can't resolve the above error by then, I have a non-widget based version where I have stripped out the Combiner and Reducer logic that will work for the class.

mwcraig commented 7 years ago

@StuartLittlefair -- I'm close to having a release that works with ipywidgets 5. Currently inclined to try a beta release in the next one-three days that you could try out. I'd release it as a beta so that you could pip install but probably won't do a formal release for ipywidgets 5 because the accordions for the file browser have some defects that are not fixable on the python side.

mwcraig commented 7 years ago

@StuartLittlefair -- can you please try out v0.3.4.b2 (now on pypi) and let me know how it goes? There are definitely still some rough edges in the styling, but it should be usable...

StuartLittlefair commented 7 years ago

Thanks @mwcraig - this works perfectly! I really appreciate the effort...

mwcraig commented 7 years ago

No problem. Please let me know if you run into an wrinkles when running it. I'd be very curious to here how the class goes.

FYI, there is a set of (very incomplete) notebooks at https://github.com/mwcraig/obs-astronomy-binder that walk through some observing basics with astropy. Feel free to use as you like.

mwcraig commented 6 years ago

@StuartLittlefair -- fyi, later this week I'll be releasing a version of reducer compatible with ipywidgets>=7. There won't actually be a release compatible with ipywidgets 5 or 6, but compatibility with 7 is almost ready.

mwcraig commented 6 years ago

@StuartLittlefair -- I'm closing this now that I've released v 0.4.0, which works with ipywidgets >=7, but please do let me know if you run into issues with it.